【问题标题】:Using Async Await inside loops在循环中使用 Async Await
【发布时间】:2019-07-16 05:03:56
【问题描述】:

我遇到了一个问题,我必须将一些存储在数组中的 JSON 数据发送到服务器。 问题是循环只是运行到下一次迭代而不等待从服务器获得响应。 我不想使用超时,因为我无法预先判断服务器的响应时间。

 async  uploadResponces(responseList) {
var idList = responseList;

for (let i = 0, j = 1; i < idList.length; i++ , j++) {
  var newArray = JSON.parse(idList[i].response)

  await this.apiConnect.postResponseTwo('submitform', newArray).then((data) => {
    self.submitStatus = data;
    alert(JSON.parse(this.submitStatus))
    if (this.submitStatus.status == "success") {
      alert(idList[i].id)
      var topush = JSON.stringify(idList[i].id)
      this.submited.push(idList[i].id)
      if (j == idList.length) {
        alert("submited array" + this.submited)
        this.deleteresponse()
      }
    }
  }).catch((errr)=>alert(JSON.stringify(errr)))
 }
}

apiconnect.postResponseTwo 是-

postResponseTwo(endpoint: string, body: any, reqOpts?: any) {
return new Promise((resolve, reject) => {
  console.log("post responce function");
  let httpHeaders = new HttpHeaders({
    'Access-Control-Allow-Origin': '*',
    'Content-Type': 'application/json',
    'Access-Control-Allow-Methods': 'GET, POST, OPTIONS, DELETE, PUT',
    'Access-Control-Allow-Headers': 'Accept,Accept-Language,Authorization,Content-Language,Content-Type',
    'Access-Control-Expose-Headers': 'Content-Length,Content-Range',

  });

  reqOpts = {
    headers: httpHeaders
  };
  let getURL = this.formUrl + endpoint;
  alert(endpoint + reqOpts);
  alert("url " + getURL);
  alert("passing object " + body);
  this.http.post(getURL, body, reqOpts).map((data) => {
    resolve(data)
    // alert("from server " + JSON.stringify(data));
    //  alert(JSON.stringify(data))

  }, err => {
    alert("error " + JSON.stringify(err));
  })
 });
}

这里的 postResponse 函数正在循环内向服务器发送数据,但 if(j==idList.length){ 并没有等待从服务器获取响应。

【问题讨论】:

  • 如果.subscribe 没有返回承诺,则循环不会“等待”。
  • @FelixKling .subscribe 正在返回一个承诺,但问题是它需要一点时间。
  • 如果它真的返回一个promise,为什么它接受一个回调? await 不在乎承诺需要多长时间才能解决。
  • 由于我不知道.post.map 会返回什么,所以我不知道这是不是一个承诺。但我不是在谈论.postResponse,我在谈论.subscribe,因为它的返回值就是你await。如果.subscribe 只是获取自定义承诺实现的已解决值的非标准方式,那么您应该使用let data = await this.apiConnect.postResponse('submitform', newArray);。但我对 angular 或 ionic 的了解还不够,无法知道这些方法的作用。
  • 老实说,您应该删除所有代码并从头开始重写。不要混合 promise 和 rx,这会让你无处可去,只有在非常特殊的情况下才应该这样做如果你真的知道你在做什么。上面的代码看起来不像你知道你在做什么,我什至怀疑它是否向服务器发送了任何请求。再加上这段代码和你第一次发布的完全不同。

标签: javascript angular ionic-framework


【解决方案1】:

如果 .subscribe really 返回一个 Promise,那么您绝对应该使用 Promise.all 而不是循环。所有的 Promise 都会同时被调用并并行运行。 Promise.all 只有在给定数组中的最后一个 Promise 被解决时才会被解决。由于并行执行,这是一种比运行循环更好的解决方案——除非你依赖于执行顺序,但是你需要链接你的 Promise 并且无论如何都不能循环。

所以,首先创建一个类似这样的 promise 数组(我没有测试过这段代码,所以它可能包含拼写错误):

// create an array of promises
const responsePromises = map((idItem) => {
  const newArray = JSON.parse(idList[i].response);
  return this.apiConnect.postResponse('submitform', newArray).subscribe((data) =>
  {
     // whatever needs to be processed here
  });
});

// execute promises in parallel either:
Promise.all(responsePromises)
  .then(results => {
    // result handling
  })
  .catch(err => {
    // error handling
  });

// or with async/await but then your enclosing
// function must be async
const results = await Promise.all(responsePromises);

您的问题不够详细,也不够详细,所以我的回答可能与您所希望的不太相符。

【讨论】:

  • 不要混合等待,然后像这一行一样使用相同的承诺 await this.apiConnect.postResponseTwo('submitform', newArray).then((data) =&gt; { 要么你去等待,在这种情况下会返回结果,要么你去然后在闭包中获取结果。您可以通过获得一本关于承诺的好书来帮自己一个忙,或者可以查看以下页面:developers.google.com/web/fundamentals/primers/promises
【解决方案2】:

您正在混合 async/await 和 rx。你实际上可以这样做(但你可能不应该这样做),因为 Observables 有一个 toPromise() 方法,你可以等待生成的 Promise。但是subscribe() 不会返回 Promise,而是返回 Subscription。 Subscription 用于取消订阅,不是 Promise,因此不可等待。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-12-30
    • 2018-01-12
    • 1970-01-01
    • 2020-08-03
    • 2020-05-30
    • 1970-01-01
    • 2017-04-29
    • 2021-10-15
    相关资源
    最近更新 更多