在承诺完成之前退出 forEach

Posted

技术标签:

【中文标题】在承诺完成之前退出 forEach【英文标题】:Exiting the forEach before promise is done 【发布时间】:2019-06-13 00:09:59 【问题描述】:

我试图在 forEach 循环内调用一个请求,但我的代码在循环完成之前退出了循环。有没有办法确保循环在下一个代码执行之前完成? (我对 Promise 比较陌生)

我的代码遵循这种格式:

let arr = [1, 2, 3, 4, 5, 6];

arr.forEach(num => 
  return request('http://google.com')
    .get('/')
    .then(() => 
      console.log(num);
    );
);
console.log('HERE');

这段代码^记录

HERE
1
2
6
4
5
3

(这些数字是随机排列的,这对我来说并不重要)

但我希望它记录

1
2
3
4
5
6
HERE

我该怎么做?

【问题讨论】:

Callback after all asynchronous forEach callbacks are completed的可能重复 代码在完成之前不会退出循环,这就是异步代码的工作方式。你触发了一堆异步调用,然后它就停止了。循环结束后调用结束。 【参考方案1】:

你不能在这种情况下使用forEach

相反,由于您使用的是基于 Promise 的并发,因此您必须将每个请求转换为 Promise (arr.map(num => ...)),然后将所有请求包装在 Promise.all 中,它本身会返回一个在之后解析的 Promise所有包装好的承诺都解决了。

let arr = [1, 2, 3, 4, 5, 6];

Promise.all(
  arr.map(num =>
    request("http://google.com")
      .get("/")
      .then(() => 
        console.log(num);
      )
  )
).then(() => 
  console.log("HERE");
);

【讨论】:

只有在请求按顺序返回时才会产生所需的结果。 并非如此,promise 可以按任何顺序解决,映射发生时它们已经被排序。但如果其中任何一个失败,'Promise.all()` 也会失败。 @Guywhotypesfast 确定最终映射结果将按顺序保存值,但 console.logs 将按解析顺序发生。 嗯,你是对的,日志会在每个 promise 被解决时出现。返回数组并在.then() 回调中记录将解决此问题。对吗? 我刚刚注意到:(the numbers are in random order, that's not really what matters to me) 所以可能没关系。【参考方案2】:

这里是另一个例子。也可以用于

let array = [1, 2, 3, 4, 5, 6];
async function processArray(arr)
  for (const num of array) 
    await request('http://google.com').get('/');
    console.log(num);
  
  console.log('Done!');


processArray(array);

【讨论】:

以上是关于在承诺完成之前退出 forEach的主要内容,如果未能解决你的问题,请参考以下文章

在继续之前如何以角度执行所有承诺?

完成后逃离承诺链[重复]

Angular forEach 等到所有承诺都完成?

在开始下一个之前等待上一个承诺的Javascript Map?

节点递归承诺永远不会退出

在返回函数的变量之前,如何等待 promise 完成?