如何让 observable 立即返回数据,之后每 5 秒返回一次数据

Posted

技术标签:

【中文标题】如何让 observable 立即返回数据,之后每 5 秒返回一次数据【英文标题】:How to get an observable to return data immediately and every 5 seconds thereafter 【发布时间】:2016-08-05 09:47:07 【问题描述】:

我想创建一个从 webapi 返回数据的 observable。我希望它立即返回数据,并每 10 秒轮询一次 API。下面的代码显示我正在使用“间隔”方法。但这会使第一组数据延迟 10 秒。如何在没有初始延迟的情况下使第一次刷新数据下降?

export class EventService 
    public events$: Observable<Event[]>;
    private _eventsObserver: Observer<Event[]>;
    private pollInterval: number = 5000;

    private _dataStore: 
        events: Event[];
    ;

    constructor(private http: Http) 
        this._dataStore =  events: [] ;

        this.events$ = new Observable(observer => this._eventsObserver = observer)
            .startWith(this._dataStore.events)
            .share();
    

    pollEvents() 
        return Observable.interval(10000)
            .switchMap(() => 
                return this.http.get('app/resources/data/scheduleevents.json')
                    .map((responseData) => 
                        return responseData.json();
                    );
            )
            .map((events: Array<any>) => 
                let result: Array<Event> = [];
                if (events["data"]) 
                    events["data"].forEach((event) => 
                        result.push(event);
                    );
                
                return result;
            );
    

【问题讨论】:

【参考方案1】:

知道了:

        .interval(5000)
        .startWith(0);

【讨论】:

但是我得到了两次 0 plnkr.co/edit/Cl5DQ7znJRDe0VTv0Ux5?p=preview @adamport 第一个零是您使用 startWith(0) 初始化的,但第二个零来自连续 4 次执行的 0-index take( 4)【参考方案2】:

使用计时器。我认为 timer 是您所需要的(请参阅 RxJS 选项卡): http://reactivex.io/documentation/operators/timer.html#collapseRxJS

可以这样使用:

Observable.timer(0, 5000).flatMap(() => apiCall())

其中0 - 发出第一个值之前的延迟,5000 - 每 5 秒后发出值

【讨论】:

reactivex.io/rxjs/class/es6/… 我不认为它已被弃用。【参考方案3】:

下面的 angualr2 是我在我的应用程序中编写的代码,它按预期工作 -

服务中--

import  Observable  from 'rxjs/Observable';
import 'rxjs/Rx';

getList(): Observable<IVM> 
    return Observable.interval(5000).startWith(0)
          .switchMap(() => 
             this._http.get(this._vmURL )
                 .map((response: Response) => <IVM>response.json().data)
                 .do(data => console.log('All: ' + JSON.stringify(data)))
                .catch(this.handleError)
             );

在组件中——

private getInstanceDetails(): void 
    this._vmDataService.getList()
        .subscribe(vmList => 
           //Do whatever you want with the vmList here :) 
        ,
        error => this.errorMessage = <any>error);

谢谢, 请让我知道你的想法。

【讨论】:

【参考方案4】:
    let timer = TimerObservable.create(0, 5000);
    this.sub = timer.subscribe(t => 
        this.yourMethod()
    );

要取消订阅,请运行this.sub.unsubscribe()

【讨论】:

【参考方案5】:
Observable.interval(5L, TimeUnit.SECONDS)
        .startWith(0)
        .observeOn(androidSchedulers.mainThread())
        .map  foobar() 

对我来说很好。 谢谢

【讨论】:

【参考方案6】:

我个人使用间隔和startWith(需要RxJs 6+),这里是一个完整的例子:

   history: any;
   historySubscription: Subscription;

   constructor(private jobService: JobService)  

   ngOnInit() 

      this.historySubscription = interval(10000).pipe(
         startWith(0),
         flatMap(() => this.jobService.getHistory())
      ).subscribe(data => 
         this.history = data;
      );

   

   ngOnDestroy() 
      this.historySubscription.unsubscribe();
   

这会在初始化时检索历史记录,然后每 10 秒检索一次。

另一种方法是使用 timer,正如@Alendorff 所解释的那样。

【讨论】:

以上是关于如何让 observable 立即返回数据,之后每 5 秒返回一次数据的主要内容,如果未能解决你的问题,请参考以下文章

如何将空 JSON 数据推送到 Observable<any[]> angular 2 类型的数组字段

RxSwift,依赖链的下载返回相同的 Observable 类型

Firebase:如何在observeSingleEvent() 之后删除Observer(withHandle:)?

Firebase Datasnapshot Observable 在通过重定向登录后不会立即更新

websocket 11

RxSwift Observeable 不会在数据更改时更新 tableview