【问题标题】:Angular - sequential execute code after for loopAngular - for 循环后的顺序执行代码
【发布时间】:2021-08-09 07:57:59
【问题描述】:

如果我需要提供更多代码或解释,请告诉我。

在 for 循环中调用服务方法后,我试图执行一些代码。我尝试了两种不同的方法。

在第一种方法中,console.log('1st After for loop') 在 for 循环之后打印,然后打印 console.log(data)

在第二种方法中,console.log('2nd- After for loop') 永远不会打印。

我想遍历列表。验证每个项目。如果不是验证不成功,显示请求确认。如果用户选择是,调用保存方法。

代码 sn-p #1:

save() {
  this.selectRowData.forEach(async s => {
    this.myService.validate(s.id).subscribe(data => {
      console.log(data);
      if(data) {
         this.myService.confirm('Please confirm..', 'Selected Rule do not match expected rules. \n Do you want to continue? ', 'Yes', 'No')
      .then((confirmed) => {
        if(confirmed) {
          console.log("User selected: Yes");
         this.myService.save();
        } else {
          console.log("User selected: No");
        }
      }).catch(() => {
        console.log("Error...");
      });
    }, (error: any) => {
      alert("Error Linking Lot");
    });
  });
  console.log('1st After for loop');
}

代码 sn-p #2:

async save() {
  await new Promise(resolve => {
    this.selectRowData.forEach(async s => {
      let validateData = await this.myService.validate1(s.id);
      console.log(validateData);
    });

  });
  console.log('2nd- After for loop');
}

service.ts

validate(id: string): Observable < boolean > {
  return this.httpClient.get < boolean > ('/RestWeb/validate?id=' + id);
}

validate1(id: string) {
  return this.httpClient.get < boolean > ('/RestWeb/validate?id=' + id).toPromise();
}

【问题讨论】:

  • 尝试使用 setTimeout() 函数。

标签: angular typescript async-await angular-promise


【解决方案1】:

您的实施存在各种问题。

save 方法的问题:

  1. 您正在使用 async,它仅适用于返回承诺的方法。
  2. 您在回调方法中对myService 调用validate 方法,该方法返回Promise Observable
  3. 如果 validate 方法返回 Promise,您可以在那里使用 await。但它返回一个Observable
  4. forEach 同步运行,但myService.validate 方法异步运行,.subscribe 方法的成功回调中的回调方法也是如此。

这就是它在记录结果之前记录'1st After for loop' 的原因。

async save 方法的问题:

您在方法中 awaiting new Promise,但不是 rejecting 或 resolveing 该承诺。

这可能就是'2nd- After for loop' 甚至没有记录的原因。

更好的方法是使用 RxJS 的 forkJoin 运算符加入所有由 myService.validate 方法返回的 Observable,然后在成功回调中登录到 subscribe 方法。像这样的:

forkJoin(
  this.selectRowData.map(({ id }: any) => this.myService.validate(id))
).subscribe(
  data => {
    console.log('save:: ', data);
    console.log('save:: 1st After for loop');
  },
  (error: any) => {
    alert('save:: Error Linking Lot');
  }
);

或者,如果您想使用promise 方法(因为您使用的是 RxJS,这没有多大意义),您也可以使用 Promise.allawait它然后记录结果,然后是消息。像这样的:

async saveAsync() {
  const responses = await Promise.all(
    this.selectRowData.map(({ id }: any) => this.myService.validate1(id))
  );
  console.log('saveAsync:: ', responses);
  console.log('saveAsync:: 2nd- After for loop');
}

这是一个 Working Sample StackBlitz 供您参考。请检查控制台以获取结果。

【讨论】:

  • const observables 和forkJoin 中都不需要使用扩展运算符(...)。使用简单:observables=this.selectRowData.map(x=&gt;this.myService.validate(s.id))forkJoin(observables)
  • 非常感谢您的解释。暂时赞成。它现在给了我很多想法。我尝试了我的代码,它正在工作。对不起,我没有解释整个场景。现在我已经更新了代码和我真正想要的。根据我的要求,我仍然卡住了。当我尝试为每个元素调用 save 时,我没有从 validate 方法中得到结果。
  • @SK。我们应该将线程集中在 StackOverflow 上。所以我建议恢复问题更新,关闭这个循环,并就这个问题提出一个新问题。
猜你喜欢
  • 2017-02-22
  • 1970-01-01
  • 1970-01-01
  • 2021-08-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-02
  • 2012-11-06
相关资源
最近更新 更多