2017-02-20 24 views
2

我正在制作一个社区广播电台的时间表,并想知道如何去更新当前的节目播放。我只是每分钟轮询服务器一次(不知道这是要走的路,但它会在推动),但看到我有从API的结束时间,我想知道如果在结束时间过后,我可以将其设置为更新,然后在下一个结束时间设置一个新的观察者。在给定时间发出API请求以更新当前广播节目Angular2 RxJS

有没有人有一个想法,我可能会做到这一点,或有更好的方法来更新当前节目?

我真正在努力的是让我的头在观察者和订户周围。例如,如何从radioShow$访问当前的end_time以查看它是否已通过Observable.interval

我将非常感谢任何帮助。

export class PlayerComponent { 

    radioShow$ = new BehaviorSubject({ 
     start_time: new Date(), 
     end_time: new Date(), 
     radio_show: { 
      id: 0, 
      name: "Loading...", 
    }); 

    constructor(
     @Inject('api') private api, 
     private http: Http) { 
      Observable.interval(1000*60) 
       .switchMap(() => http.get(api + '/schedule/current/show') 
       .map(res => res.json())) 
       .subscribe(this.radioShow$); 
    } 
} 

查看player.component.html:

<div class="io-radio-player"> 
    <p class="schedule-times">{{(radioShow$ | async).start_time | date:"HH:mm"}}–{{(radioShow$ | async).end_time | date:"HH:mm"}}</p> 
    <h3 class="margin-none"> 
    <a [routerLink]="['/radio-shows', (radioShow$ | async).radio_show.id]">{{(radioShow$ | async).radio_show.name | uppercase}}</a> 
    </h3> 
</div> 

@martins代码的工作,但是这是我用到底:

radioShow$ = new BehaviorSubject({ 
    start_time: new Date(), 
    end_time: new Date(), 
    radio_show: { 
     id: 0, 
     name: "Loading..." 
    } 
}); 
timer = new Subject(); 

@Component({ 
    selector: 'app-player', 
    templateUrl: './player.component.html' 
}) 
subject = new Subject(); 

    let request = http.get(api + '/schedule/current/show') 
     .switchMap(() => http.get(api + '/schedule/current/show') 
     .map(res => res.json())) 
     .repeatWhen(() => this.subject) 
     .publishReplay() 
     .refCount(); 

    request 
     .subscribe(this.radioShow$); 

    request 
     .map(response => { 
      // calculate the delay 
      return Math.abs(new Date(response.end_time).getTime() - (new Date()).getTime()); 
     }) 
     .concatMap(delay => Observable.of(null).delay(delay)) 
     .subscribe(this.subject); 

回答

1

我觉得你可以做这与repeatWhen()运营商。你只需要使用一个额外的Subject,告诉它,当你要重复的请求:

let subject = new Subject(); 

const response = { 
    start_time: new Date(), 
    end_time: new Date(), 
    radio_show: { 
    id: 0, 
    name: "Loading..." 
    } 
}; 

let radioShow$ = Observable.defer(() => { 
    // return http.get(...); 
    return Observable.of(response); 
    }) 
    .do(() => console.log('create new HTTP request')) 
    .repeatWhen(() => subject) 
    .publishReplay() 
    .refCount(); 

// responses 
radioShow$ 
    .startWith(response) 
    .subscribe(val => console.log('Response:', val)); 

// pooling delay 
radioShow$ 
    .map(response => { // calculate the delay 
    // return response.end_time - (new Date()).getTime(); 
    return Math.random() * 1000; 
    }) 
    .concatMap(delay => Observable.of(null).delay(delay)) 
    .subscribe(subject); 

见现场演示:https://jsbin.com/kutabiw/6/edit?js,console

这使得每个调用之间的随机0-3s延迟来模拟你通常会计算延迟。

+0

非常感谢您的回复,这似乎让我更接近解决方案。我不得不为Angular2重做它的https://plnkr.co/edit/vzSXA6vItalQVTQNvzN9。你熟悉BehaviourSubjects吗?正如我想维护'radioShow $'一样。我也不确定'http.get()'适合在哪里。如果这是一种痛苦,我很抱歉,我非常新的RxJS和Angular2。 – Sarcoma

+0

@Sarcoma我稍微更新了我的答案。你可以看到'http.get(...)'的位置。我还添加了'.publishReplay().refCount()'和'.do()'以确保我们没有提出更多的请求。为什么你需要使用'BehaviorSubject'?在这种情况下实际上并不理想,因为'repeatWhen()'取消订阅并订阅其源Observable。我们使用'BehaviorSubject'而不是我们总是会收到默认值。我想应该有一种方法让你不要使用'BehaviorSubject'。 – martin

+0

再次感谢,我再看一次。我使用'BehaviourSubject'来设置初始值,一旦我得到一个响应,它们被新内容所取代,我并不真正了解它是什么或它是如何做的,但它意味着我所有的调用'(radioShow $ | async).name'等只能发出一个请求,并且不需要'?'像'(radioShow $ | async)。?name'。 – Sarcoma