rxjs,递归调用 api 直到所有项目都被获取

Ced*_*Ced 1 rxjs angular

我需要调用 api 并从端点获取所有项目。但是,我们一次只能获取 100 个项目。

响应如下所示:

{
    elements: Array<any>,
    totalCount: number,
}
Run Code Online (Sandbox Code Playgroud)

和端点将/api/items?drop=${drop}&take=100drop被用来进行分页。

我认为这会涉及到 scan 和 takeWhile 操作符的某个地方..这是我得到的:

    const subject = new Subject();
    const rec = subject.pipe(
        scan((acc: number, curr: number) => (curr + 100), 0),
        switchMap(drop => this.http.get(`api/items?drop=${drop}&take=100`)),
        takeWhile((r: any) => r.elements.length === 100),
        tap(r => subject.next())
    );
Run Code Online (Sandbox Code Playgroud)

Ric*_*sen 6

您不需要知道将返回多少个元素,只需知道它永远不会返回多少个 :)

Observable.range(0, 1000000).pipe(
  concatMap(page => this.http.get(`api/items?drop=${page * take}&take=${take}`))
  takeWhile(results => results.elements.length === take)
)
Run Code Online (Sandbox Code Playgroud)

起初我认为使用rangeas source 会堆积请求并破坏分页的目的,但是 concatMap 提供了自动限制。

来自learnrxjs.io/operators/transformation/concatmap

注意 concatMap 和 mergeMap 之间的区别。因为 concatMap 在前一个完成之前不会订阅下一个 observable,所以将首先发出延迟 2000 毫秒的源值。将此与立即订阅内部 observable 的 mergeMap 进行对比,具有较小延迟(1000 毫秒)的 observable 将发出,然后是需要 2000 毫秒才能完成的 observable。

这是concatMap的一个测试,它显示getPage在之前的结果发出之前不会被调用

const take = 100;
const getPage = (page) => {
  console.log('reading page', page);
  return Rx.Observable.of(page).delay(1000);
}

Rx.Observable.range(0,3)
  .concatMap(getPage)
  .subscribe(results => console.log('concatMap results', results));
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.5.10/Rx.js"></script>
Run Code Online (Sandbox Code Playgroud)

mergeMap 相比,它使所有调用都getPage立即

const take = 100;
const getPage = (page) => {
  console.log('reading page', page);
  return Rx.Observable.of(page).delay(1000);
}

Rx.Observable.range(0,3)
  .mergeMap(getPage)
  .subscribe(results => console.log('mergeMap results', results));
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.5.10/Rx.js"></script>
Run Code Online (Sandbox Code Playgroud)