等待多个订阅的打字稿

时间:2016-11-30 23:49:15

标签: angular typescript rxjs observable angularfire2

我有一个包含ID列表的Observable。对于每个ID,我希望得到ID所代表的对象。这样做需要我获得每个对象的可观察性。在继续之前如何确保收到所有对象?

这是数据库中的多对多关系。

getExercises(programKey: string): Observable<Array<Exercise>> {
    let source = Observable.create(observer => {
      // ... stuff here ...
      programExercises.subscribe(programExercisesSnapshot => {
        let exercises = Array<Exercise>();
        programExercisesSnapshot.forEach(programExercise => {
          let exercise = this.getExercise(programExercise.ExerciseKey); // Returns Observable<Exercise>
          exercise.subscribe(exerciseSnapshot => exercises.push(exerciseSnapshot)); // TODO: Need to await all these subscriptions before calling observer.next()
        });
        observer.next(exercises);
      });

      return () => { }; // Dispose
    });

    return source;
}

提前致谢!

1 个答案:

答案 0 :(得分:1)

嗯,除了由于Observable返回Array看起来有点奇怪之外,我就是这样做的:

getExercises(programKey: string): Observable<Array<Exercise>> {
    // ... stuff here ...
    return programExercises
        // assuming that programExercisesSnapshot is an array or can be easily converted to it
        .flatMap(programExercisesSnapshot => Observable
            .from(programExercisesSnapshot)
            .flatMap(programExercise => this.getExercise(programExercise.ExerciseKey))
            .bufferCount(programExercisesSnapshot.length));

现在让我们看看它应该如何运作。让我们从内心开始。

  1. 我们从数组programExercisesSnapshot生成observable,然后逐个发出它的元素;
  2. 我们会抓住这些元素,并使用this.getExercise(programExercise.ExerciseKey)调用flatMap()来自bufferCount()调用返回的observable的结果替换;
  3. programExercisesSnapshot.lengththis.getExercise()元素收集到一个数组中并作为结果发出。
  4. 因此,整个管道会发出programExercises次调用的结果数组。

    现在,外部事情做了以下事情:

    1. 它需要programExercises.subscribe();
    2. 发出的批次
    3. 将它们替换为先前描述的observable发出的结果(例如数组);
    4. 并将这些结果作为自己的结果发布。
    5. 利润! :)

      您在原始解决方案中遗漏的另一件事是清理。执行getExercises(programKey: string): Observable<Exercise> { // ... stuff here ... return programExercises // assuming that programExercisesSnapshot is an array or can be easily converted to it .flatMap(programExercisesSnapshot => Observable.from(programExercisesSnapshot)) .flatMap(programExercise => this.getExercise(programExercise.ExerciseKey)); 时,您还需要手动取消订阅。按照我的建议去做,不需要它 - rxjs会为你照顾它。

      另外,正如我在开头所说的那样,在observable中返回一个数组看起来有点奇怪。我希望你有充分的理由这样做。 :)否则你可能要考虑将它逐个转换为可观察的发射元素。

      <强>更新。

      由于作者承认:)这里不需要数组是另一种解决方案,更简单和优雅:

      pixelsChecked