简体   繁体   English

RxJS Observable with Subject,通过计时器和combineLatest进行轮询不会触发

[英]RxJS Observable with Subject, polling via timer and combineLatest does not fire

I wrote a function to do polling on an API that is also able to do pagination. 我写了一个函数来对一个也可以进行分页的API进行轮询。 Herefor the pagination is done using a Subject Observable and polling is done with the timer method (I also tried interval with the same result). 因此,使用Subject Observable完成分页,并使用计时器方法完成轮询(我也尝试使用相同结果的间隔)。

Here is my code: 这是我的代码:

  getItems(pagination: Subject<Pagination>): Observable<ListResult<Item>> {
    let params: URLSearchParams = new URLSearchParams();

    return Observable
      .timer(0, 5000)
      .combineLatest(
        pagination,
        (timer, pagination) => pagination
      )
      .startWith({offset: 0, limit: 3})
      .switchMap(pagination => {
        params.set('skip', pagination.offset.toString());
        params.set('limit', pagination.limit.toString());
        return this.authHttp.get(`${environment.apiBase}/items`, {search: params})
      })
      .map(response => response.json() as ListResult<Item>)
      .catch(this.handleError);
  }

The expected behavior would be: HTTP request is fired every 5 seconds AND when the user changes the page. 预期的行为是:HTTP请求每5秒触发一次,当用户更改页面时。

This is what happens: First HTTP request is fired, but then no other request is sent to the server UNTIL pagination is used. 这就是:第一个HTTP请求被触发,但是没有其他请求被发送到服务器UNTIL分页被使用。 After pagination is used the first time, the polling starts working too. 在第一次使用分页后,轮询也开始工作。

It's the first time I'm using Observables so I'm pretty sure I missed something, but I can't see what it might be. 这是我第一次使用Observables,所以我很确定我错过了什么,但我看不出它可能是什么。

I also tried this approach (maybe it was missing the timer counter in startWith), but it didn't change anything. 我也试过这种方法(也许它在startWith中缺少计时器计数器),但它没有改变任何东西。

[...]
  .combineLatest(
    pagination
  )
  .startWith([0, {offset: 0, limit: 3}])
[...]

The combineLatest() operator requires all source Observables to emit at least one item. combineLatest()运算符要求所有源Observable都发出至少一个项。

Your demo makes only one request because you're using .startWith() . 您的演示只生成一个请求,因为您正在使用.startWith() The combineLatest() never emits because the pagination is a Subject and it probably never emits any item. combineLatest()永远不会发出,因为pagination是一个Subject ,它可能永远不会发出任何项目。

So one option is to move .startWith() : 所以一个选择是移动.startWith()

.combineLatest(
  pagination.startWith({offset: 0, limit: 3}),
  (timer, pagination) => pagination
)

But maybe this doesn't help you much because you're ignoring all items coming from the timer() and you're using just pagination . 但也许这对你没什么帮助,因为你忽略了来自timer()所有项目timer()而你只是使用了pagination So maybe you could use just merge() to refresh the list from one of the sources. 所以也许你可以使用merge()从其中一个源刷新列表。 Then the timer() independently increases the offset. 然后timer()独立地增加偏移量。

Observable
  .timer(0, 1000)
  .map(i => { return {offset: i*3, limit: 3}})
  .merge(pagination.startWith({offset: 0, limit: 3}))
  .switchMap(pagination => {
    return Observable.of(pagination).delay(200)
  })
  .subscribe(val => console.log(val));

Make sure you are following below steps 请确保您遵循以下步骤

creating onservable data 创建可观察的数据

you have a observable verable and you are pushing data by observable.next(value); 你有一个可观察的可操作数,你正在通过observable.next(value);推送数据observable.next(value);

getting data in a subject or behourSubject 获取主题或behourSubject中的数据

Where you want to get the data you are declaring a Subject type variable and access it by subscribing it. 在想要获取数据的地方,您要声明一个主题类型变量并通过订阅它来访问它。

private val: Subject = YourObservable;
private uiValue: string;

val.sunscribe((val) => {
   uiVal = val;
});

Now you can use the uiVal anywhere which will update in each inteval. 现在,您可以在任何位置使用uiVal进行更新。

you can test both the pieces separately by just making the console.log to make sure everything is working file 你可以通过制作console.log来分别测试这两个部分,以确保一切正常

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM