Angular - for 循环后顺序执行代码

Angular - sequential execute code after for loop

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

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

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

之前

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

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

代码片段#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');
}

代码片段#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();
}

您的实施存在各种问题。

save 方法的问题:

  1. 您使用的 async 仅适用于 return 承诺的方法。
  2. 您在回调方法中调用 myService 上的 validate 方法,return 是一个 Promise Observable.
  3. 如果验证方法 returned a Promise,您可以在那里使用 used await。但它 return 是 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 方法编辑的 Observables return然后在 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.all , await 它然后记录结果,然后是消息。像这样:

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');
}

Here's a Working Sample StackBlitz for your ref. Please check the console for the result.