【问题标题】:async and await in angular api response角度 api 响应中的异步和等待
【发布时间】:2021-12-13 22:54:54
【问题描述】:

我正在尝试一步一步地完成任务。

我在方法中有一个 for 循环:

async changeTimeStep3() {
  for (let i = 1; i < 10; i++) {
    await this.do(i)
  }
}

对于每一步都必须做() 任务。

do(i) {
  this.http
    .getDataFromServer(
      "api/example?id=" +i
    )
    .subscribe((response) => {
     console.log(i);
    });
}

  

我想等待得到回复,回复后转到下一个i

但console.log打印不起作用:

2
3
5
1
4
7
8
9
6

注意从 api 接收响应的时间不固定。

有什么帮助吗?

【问题讨论】:

  • do 没有返回等待的承诺...
  • 为什么?以及如何以正确的方式做? @jonrsharpe
  • 我不知道为什么它不返回一个承诺,你大概是这样写的,或者为什么你在等待它,即使它没有。如果您想等待它,请尝试实际返回一个承诺,该承诺会在工作完成时解决(或者如果失败则拒绝)。
  • 我意识到这并不能回答你的问题,但是这样的调用是一种反模式。如果需要在循环中等待多个调用,则需要将集合传递给查询。

标签: javascript angular asynchronous async-await


【解决方案1】:

要让您的循环以正确的顺序打印出值,您可以将您的 observables 转换为 Promise,因此只要 HTTP 调用尚未解决,您的 await 就会阻止 for-循环。

import { firstValueFrom } from 'rxjs';

...

async do(i: number) {
  await firstValueFrom(
    this.http
      .getDataFromServer(
        "api/example?id=" +i
      )
  );
  console.log(i);
}

使用firstValueFromlastValueFrom 是RxJS 方法从一个可观察对象中获取一个promise 作为返回值(因为toPromise 已被弃用,您可以阅读更多关于here 的信息。

【讨论】:

    【解决方案2】:

    您可以返回 Promise 并使用 resolve() 作为 ajax 的响应部分。喜欢:

    do(i) {
      return new Promise((resolve, reject) => {
        this.http.getDataFromServer("api/example?id=" +i).subscribe((response) => {
          resolve(response);
        }, (error) => {
          console.error(error);
          reject();
        });
      });
    }
    

    【讨论】:

    • 我正在编辑。是的,它是平行的。我也放了顺序模型。 @jonrsharpe
    • for (let i = 0; i &lt; x; i++) {} 中的循环与for (const i of arr) {} 模型不同。 @jonrsharpe
    • 刚才我想出了一个更好的答案...
    • 工作如虎添翼,谢谢!!
    • 这种笨拙的 new Promise 包装一个 Observable 真的不是要走的路。我不知道为什么 OP 将其标记为已接受。 @Batajus 上面的回答要好得多。
    【解决方案3】:

    这里的问题是 do 不是异步方法;它是一种触发异步方法的同步方法。因此,等待立即完成。

    你可以这样做:

    do(i) {
      return firstValueFrom(this.http
        .getDataFromServer(
          "api/example?id=" +i
        ))
    }
    

    它将 observable 转换为 Promise 并返回它。所以,现在 do() 方法返回一个异步对象。从do方法输出;你可以使用管道:

      return firstValueFrom(this.http
        .getDataFromServer(
          "api/example?id=" +i
        ).pipe(tap((result) => {console.log(i);}))
    

    话虽如此,在 Angular 中使用 async/await 是不寻常的。 RXJS 运算符通常被认为是正确的方法。可能与concat

    【讨论】:

    • 订阅返回订阅,而不是承诺 - 这与 OP 当前存在的问题相同。
    • 我认为这有一个完全不同的问题,但很好地呼吁承诺/订阅问题。
    • 它有同样的问题,因为你正在等待一些不是承诺的东西,因此等待它是没有意义的,因为它不会同步行为。
    • @jonrsharpe 我编辑了答案;所以现在应该更准确了。
    猜你喜欢
    • 2018-07-08
    • 2011-09-03
    • 1970-01-01
    • 2020-09-26
    • 2020-12-03
    • 2017-12-17
    • 1970-01-01
    • 2020-12-09
    • 1970-01-01
    相关资源
    最近更新 更多