是否保证for ... of循环内的异步调用将按顺序返回?

时间:2019-01-10 08:20:35

标签: javascript loops for-loop asynchronous

目前,我有一个代码,该代码必须遍历数组并为每个交互请求一个API。

看起来像这样

let arrayOfIds = [1, 2, 3, 5, 8, 13, 21];
let order = []
let count = 0;

for (let id of arrayOfIds) {
  asyncAPICall(id)
    .then((result) => {
      order.push(count++);
    });
}

问题是是否保证在count++数组中推入的order总是 将是[0, 1, 2, 3, 4, 5, 6](以正确的升序排列) ?

我已经测试过几次了,但是我没有足够的信心在生产中使用它。

我也进行了搜索,但是我发现大多数是其他语言的,所以不能直接回答我的问题。

谢谢!


其他问题:

我该怎么做才能确保顺序正常?

3 个答案:

答案 0 :(得分:2)

不能保证您的请求将按照严格的顺序得到解决。

您的代码能够正常工作的原因是,您的请求得到解决时,您正在增加count变量。因此,对于您而言,解决哪个请求都没关系-结果将相同(计数++)。

尝试使用order.push(count++);代替console.log(result)

答案 1 :(得分:1)

不,它们是按顺序发送的,但是由于它们是异步的,因此它们可能会无序响应。

答案 2 :(得分:1)

如果您要保证兑现承诺,可以使用Promise.all

我已经相应地重写了代码,但有一点副作用,控制台在迭代过程中会记录数组值,以便您可以在控制台中查看运行顺序。

我为您的asyncAPICall创建了一个新的承诺来表示它。请注意,resolve参数是成功承诺的返回值。

Promise的唯一陷阱是,如果其中一个承诺失败,整个链条都会失败,这有很多解决方法,但这就是整个“另一个故事”

let arrayOfIds = [1, 2, 3, 5, 8, 13, 21];
let order = []
let count = 0;

const asyncAPICall = (i) => new Promise ((resolve, fail) => {
    console.log("i am a new promise", i)
    resolve(order.push(count++))
})

const allPromises = arrayOfIds.map(arrayValue => asyncAPICall(arrayValue))
Promise.all(allPromises)
    .then((newArray) => console.log(newArray))
    .catch((e) => console.log('something has gone wrong', e))

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all