如何从Angular 6和RxJs 6的forkJoin订阅中返回值?

时间:2018-09-25 10:43:42

标签: angular rxjs6

private save(payload) {

  const newMedias: Observable<Media>[] = [];
  const newMediaInStepIndex: number[] = [];

  (payload.formData.steps).forEach((step: Step, stepIndex: number) => {
    const media: Observable<Media> = this.createOneMedia(step);
    if (media !== undefined) {
      newMedias.push(media);
      newMediaInStepIndex.push(stepIndex);
    }
  });

  forkJoin(newMedias).subscribe(medias => {
    medias.forEach((media, i) => {
      console.log('Media created with id: ' + media.id + ' in step ' + newMediaInStepIndex[i]);
      payload.formData.steps[newMediaInStepIndex[i]].media[0].id  = media.id;
    });
  });

  return this.createRecipe(payload);
}

我的问题是,以下行是异步执行的,因此不在返回结尾之前:

payload.formData.steps[newMediaInStepIndex[i]].media[0].id  = media.id;

所以一旦订阅结束,我需要返回结尾。我认为我们必须将此功能切成两半。

重要提示:返回保存(有效载荷)

3 个答案:

答案 0 :(得分:1)

subscribe方法具有3个参数函数。

1)next(),您曾经使用过
2)error(),您还没有
3)complete(),在流完成后运行。

因此,您可以像这样在完整的回调中添加createRecipe:

forkJoin(newMedias).subscribe(medias => {
    medias.forEach((media, i) => {
      console.log('Media created with id: ' + media.id + ' in step ' + newMediaInStepIndex[i]);
      payload.formData.steps[newMediaInStepIndex[i]].media[0].id  = media.id;
    });
  },
err => {},
() => {
    this.createRecipe(payload);
});

在加载所有有效负载后,这将调用createRecipe方法(一旦newMedias数组中的所有可观察对象都已解析)。

希望这会有所帮助。

答案 1 :(得分:0)

需要一个函数来返回从forkjoin合并的可观察对象,然后从其他地方进行订阅

private saveToServer(payload) {

  (payload.formData.steps).forEach((step: Step, stepIndex: number) => {
    const media: Observable<Media> = this.createOneMedia(step);
    if (media !== undefined) {
      newMedias.push(media);
      newMediaInStepIndex.push(stepIndex);
    }
  });

  return forkJoin(newMedias) 
}


private save(payload) { 

  this.saveToServer(payload).subscribe(medias => {
    medias.forEach((media, i) => {
      console.log('Media created with id: ' + media.id + ' in step ' + newMediaInStepIndex[i]);
      payload.formData.steps[newMediaInStepIndex[i]].media[0].id  = media.id;

      //call it here
      this.createRecipe(payload);
    });
  }); 
}

答案 2 :(得分:0)

解决方案结束了吗?

private save(p): Observable<Action> {

    const payload = JSON.parse(JSON.stringify(p));

    const newMedias: Observable<Media>[] = [];
    const newMediaInStepIndex: number[] = [];

    (payload.formData.steps).forEach((step: Step, stepIndex: number) => {
        const media: Observable<Media> = this.createOneMedia(step);
        if (media !== undefined) {
          newMedias.push(media);
          newMediaInStepIndex.push(stepIndex);
        }
    });

    if (newMedias.length > 0) {
        return forkJoin(newMedias).pipe(mergeMap( (medias) => {
          medias.forEach((media, i) => {
            payload.formData.steps[newMediaInStepIndex[i]].media[0].id = media.id;
          });
          return this.createRecipe(payload);
        }));
    } else {
        return this.createRecipe(payload);
    }

}

我在subscribe中将mergeMap换成pipe。我在Observable<Action>的返回中返回forkJoin,并在save(p)的末尾返回。

我添加以下内容:const payload = JSON.parse(JSON.stringify(p));,因为p来自@ngrx