typescript 带有Subject的RxJS Observable,通过计时器和combineLatest进行轮询,但不会触发

apeeds0o  于 2023-05-01  发布在  TypeScript
关注(0)|答案(2)|浏览(115)

我写了一个函数在一个API上做轮询,这个API也可以做分页。在这里,分页是使用Subject Observable完成的,轮询是使用timer方法完成的(我也尝试了interval,结果相同)。
下面是我的代码:

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);
  }

预期行为为:HTTP请求每5秒触发一次,并且在用户更改页面时触发。
这是发生了什么:第一个HTTP请求被激发,但是在使用分页之前,没有其他请求被发送到服务器。第一次使用分页后,轮询也开始工作。
这是我第一次使用Observables,所以我很确定我错过了一些东西,但我看不到它可能是什么。
我也尝试过这种方法(可能是startWith中缺少了计时器计数器),但它没有改变任何东西。

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

5vf7fwbs1#

combineLatest()操作符要求所有源Observables至少发出一个项目。
您的演示只发出一个请求,因为您使用的是.startWith()combineLatest()永远不会发出,因为paginationSubject,它可能永远不会发出任何项。
因此,一个选项是移动.startWith()

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

但这可能对您没有多大帮助,因为您忽略了来自timer()的所有项,而您只使用了pagination。因此,您可以只使用merge()来刷新其中一个源的列表。然后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));
0md85ypi

0md85ypi2#

确保您遵循以下步骤

创建可观测数据

您有一个Observable变量,并且按observable.next(value);推送数据

将数据放入Subject或Behavior Subject

在想要获取数据的地方,您声明了一个Subject类型变量,并通过订阅它来访问它。

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

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

现在您可以在任何地方使用uiVal,它将在每个interval中更新。
您可以通过制作console.log来分别测试这两个部件,以确保一切正常。

相关问题