【问题标题】:Angular synchronous calls with observables带有可观察对象的角度同步调用
【发布时间】:2021-05-25 18:46:09
【问题描述】:

我有一种情况,我在我的打字稿文件中定义了一个变量diary: Diary。当用户单击某个保存按钮时,我必须执行f1,该函数具有以下结构:

public f1() {
   if (condition 1) {
      this.service.serviceCall(param).subscribe(res =>
         diary.firstPage.push(res)
      )
   }

   if (condition 2) {
       this.service.serviceCall(param).subscribe(res =>
          diary.secondPage.push(res)
   }

   if (condition 3) { ... }

   ...
}

f1() 在 f2() 之前执行,它执行以下操作:

public f2() {
   this.diaryService.saveDiary(diary).subscribe();
}

由于f1修改了diary标签,我必须确保f2只有在f1的所有订阅都完成后才执行。我该怎么做?

【问题讨论】:

  • 任何需要在 observable 完成后执行的逻辑都应该进入subscribe(res => {}) 块。
  • 问题是:从哪里开始?我不知道f1() 中哪个订阅会是第一个订阅。有时只执行一个,有时一个都不执行,有时全部执行。

标签: angular synchronization subscription


【解决方案1】:

在这里考虑 Promise 方法应该很容易,您等待所有响应,然后最后进行保存调用:

public async f1() {
  try {
    if (condition 1) {
        const res = await this.service.serviceCall(param).toPromise();
        diary.firstPage.push(res)
    }

    if (condition 2) {
        const res = await this.service.serviceCall(param).toPromise();
        diary.secondPage.push(res)
    }

    //at the end
    this.f2();

  } catch() {
    // something heer
  }
}

这也可以使用forkJoin 来解决,您可以根据条件准备一个 Observable 数组,最后在 forkJoin 订阅中调用f2。这为您提供了并行调用的优势。

ForkJoin

public f1() {
  const allApis: any = {};
  
  if (condition 1) {
    allApis.firstPage = this.service.serviceCall(param);
  }

  if (condition 2) {
      allApis.secondPage = this.service.serviceCall(param);
  }

  //at the end
  forkJoin(allApis).pipe(tap((responses) => {
    Object.entries(responses).forEach(([k, v]) => {
      diary[k].push(v)
    });
  })).subscribe(() => {
    this.f2()
  });
}

【讨论】:

  • 这样的东西正是我想要的。只有在准备好 observables 数组之后,我才考虑使用forkJoin。谢谢!
  • @Rexam:它的缺点是等待每个服务调用完成后再执行下一个,forkJoin 会处理这个问题。使用一些额外的逻辑来更新响应的适当数组。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-01-30
  • 2013-12-20
  • 1970-01-01
  • 1970-01-01
  • 2022-11-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多