Angular RxJs在阵列中可观测

Angular RxJs在阵列中可观测,angular,rxjs,angularfire2,rxjs6,Angular,Rxjs,Angularfire2,Rxjs6,我正在使用angularfire,我得到了一个连续的阵列流,其中包含任务ID。我需要获取阵列中每个id的任务文档作为新的可观察对象。然后将任务文档数组返回到流中,这样我就可以在组件中订阅它并显示任务列表 到目前为止,我用mergeMap得到了它。我分割阵列,获取任务文档并将它们返回到流中。我的解决方案唯一的问题是,当我订阅可观察到的时,我没有得到一系列任务,但每个任务都是一个单一的变化,我不能循环使用ngFor。在这种情况下,使用toArray()操作符不起作用,因为它是一个永不结束的连续流 这

我正在使用angularfire,我得到了一个连续的阵列流,其中包含任务ID。我需要获取阵列中每个id的任务文档作为新的可观察对象。然后将任务文档数组返回到流中,这样我就可以在组件中订阅它并显示任务列表

到目前为止,我用mergeMap得到了它。我分割阵列,获取任务文档并将它们返回到流中。我的解决方案唯一的问题是,当我订阅可观察到的时,我没有得到一系列任务,但每个任务都是一个单一的变化,我不能循环使用ngFor。在这种情况下,使用toArray()操作符不起作用,因为它是一个永不结束的连续流

这是我目前的代码:

this.db.collection(`games/${gameId}/missions`).valueChanges().pipe(
    mergeMap(missions => missions),
    mergeMap((mission: any) => {
        return this.db.doc(`missions/${mission.id}`).snapshotChanges();              
    }),
);
这将在单个事件中生成以下输出:

{ id: 1, missionProperties }
{ id: 2, missionProperties }
{ id: 3, missionProperties }
但我想把它作为一系列任务:

[
    { id: 1, missionProperties },
    { id: 2, missionProperties },
    { id: 3, missionProperties }
]

使用扫描操作符进行聚合

this.db.collection(`games/${gameId}/missions`).valueChanges().pipe(
  switchMap(missions =>
      from(missions).pipe(
        mergeMap(mission => this.db.doc(`missions/${mission.id}`).snapshotChanges()),
       scan((acc, curr) => [curr, ...acc], [])
      ),
)

可以使用缓冲区运算符


编辑:

of(1, 2, 3, 4, 5).pipe(
  scan((acc, curr) => { acc.push(curr); return acc; }, []),
).subscribe(x => console.log(x)); // prints [1] [1,2] [1,2,3]....
我刚刚看到toArray()操作符:

of(1, 2, 3, 4, 5).pipe(
  toArray(),
).subscribe(x => console.log(x));

编辑2:

of(1, 2, 3, 4, 5).pipe(
  scan((acc, curr) => { acc.push(curr); return acc; }, []),
).subscribe(x => console.log(x)); // prints [1] [1,2] [1,2,3]....

谢谢@Fanchung,这可以工作并将每个任务添加到阵列中,但当firebase中发生变化时,我会重新获得所有ID,并在阵列中多次执行相同的任务。我应该把扫描移到内部可观察的位置吗?如果你把第一个mergeMap改成switchMap,它会工作的。当源可观测发射时,它将取消内部可观测。我更新了答案啊,我明白了!这是有道理的,但对于rxjs来说,它往往不是您所期望的……仍然是相同的问题。只需重构代码并将扫描移到内部可观察状态。现在应该可以了。忘记扫描正在累积所有内容。但这样你就不再在阵列上循环。SwitchMap为我们提供了每个事件的ID数组,需要循环以获取相关数据并合并它。谢谢@MoxxiManagarm,但是我如何知道设置缓冲区的大小?任务的数量可能会有所不同。也许我不清楚,但你可以使用
缓冲区。我的意思是有几个缓冲操作符。你可以选择哪一个最适合你。但是我刚刚看到有一个更适合你的答案:-)在这种情况下,编辑我的应答缓冲区似乎不起作用,因为它是一个永不结束的连续流。因此,缓冲区永远不会被释放。缓冲区在条件适合时被释放,甚至在可观察对象完成之前<代码>的(1,2,3,4,5)。管道(缓冲计数(2))
将发出[1,2][3,4][5]。但是你对
toArray()
的回答是正确的。基于此,我猜你可能想考虑一下扫描,我再次编辑了我的答案