简体   繁体   English

RXJS 将单个可观察对象转换为可观察对象数组

[英]RXJS convert single observable to array of observables

I have an API ( getNewStories ) that returns the data as an array of numbers(ids) such as [1,2,3,4...].我有一个 API ( getNewStories ),它将数据作为numbers(ids)数组返回,例如 [1,2,3,4...]。 There is another API ( getItem ) that uses the number(id) and give its details.还有另一个 API ( getItem ) 使用number(id)并提供其详细信息。

How can I accomplish this with rxjs operators, so that I should only subscribe to it once and it gives me an array of the records with those ids?如何使用 rxjs 运算符完成此操作,这样我应该只订阅一次它,它会给我一个带有这些 id 的记录数组?

I am able to accomplish this using 2 subscriptions, but I want it with one.我可以使用 2 个订阅来完成此操作,但我想要一个。 Is it possible?可能吗? and if it's, then, how?如果是,那么,如何?

this.hnService.getNewStories().subscribe(data => {
  // data is [1,2,3,4,5]
  // create an array of observables for all the ids and get the record for that id
  const observables = data.map(item => this.hnService.getItem(item));
  // use forkJoin to combine the array to single results variable
  forkJoin(...observables).subscribe(results => {
    this.stories = results;
  });
});

with this I have to subscribe to both the APIs.有了这个,我必须订阅这两个 API。

You were going the right direction with using forkJoin :您使用forkJoin正确的方向前进:

this.hnService.getNewStories()
  .pipe(
    concatMap(data => {
      const items$ = data.map(item => this.hnService.getItem(item));
      return forkJoin(...items$);
    }),
  )
  .subscribe(allItems => ...);

forkJoin will wait until all source Observables complete and only then emit all results as a single array. forkJoin将等待所有源 Observables 完成,然后才将所有结果作为单个数组发出。

I think you can achieve this using a flattening operator like this.我认为您可以使用这样的展平运算符来实现这一点。

this.hnService.getNewStories().pipe(
            .mergeMap(data => this.hnService.getItem(data))
            .subscribe(res => this.stories = res);

Other option can be to create two observable streams and use a combineLatest.其他选项可以是创建两个可观察的流并使用 combineLatest。

You can simply have implemented as in the the following snippet: (Yes, mergeAll flattens an observable containing an array, for further explanation refer to @Martin's post about the Best way to “flatten” an array inside an RxJS Observable )您可以简单地按照以下代码片段实现:(是的, mergeAll将包含数组的可观察对象展平,有关进一步说明,请参阅@Martin 关于“展平” RxJS 可观察对象内的数组的最佳方法@Martin's帖子)

getNewStories().pipe(mergeAll(), concatMap(this.getItem), toArray()).subscribe()

You can try running the following snippet:您可以尝试运行以下代码段:

 const { of } = rxjs; const { concatMap, toArray, mergeAll } = rxjs.operators; function getItem(x) { return of({ item: x }) } of([1, 2, 3, 4]).pipe( mergeAll(), concatMap(getItem), toArray() ).subscribe(console.log)
 <script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.6.2/rxjs.umd.min.js"></script>

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

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