运行 使用 Promise.all 和映射函数按顺序承诺

Run promises sequentially with Promise.all and a map function

我一直在尝试使用批处理数组并使用 Promise.all 和映射函数按顺序触发请求:

const slowAsync = (i) => {
  return setTimeout(() => {
     return Promise.resolve(i);
  }, 1000)
}

const batchedIds = [[1,2], [3,4], [5,6]];

batchedIds.map(async batch => {
  const response = await Promise.all(batch.map(id => {
    return slowAsync(id);
  }));
  
  console.log(response);
})

现在控制台会立即记录所有内容

//after 1 second
[1, 2]
[3, 4]
[5, 6]

但我希望它以 1 秒的差异记录承诺的每个解决方案

//after 1 second
[1, 2]
//after 1 second
[3, 4]
//after 1 second
[5, 6]

是否可以在没有递归或库的情况下使用 map 函数来做到这一点?

您的 slowAsync 功能未正确实现。在 setTimeout 回调中返回某些内容无效。 setTimeout 本身 returns 是一个数字标识符,而不是承诺。

其次,您应该将 .map() 迭代替换为 for 循环,并将所有这些都包装在 async 函数中,以便您可以使用 await.

更正如下:

const slowAsync = (i) => new Promise(resolve =>
  setTimeout(() => resolve(i), 1000)
);

const batchedIds = [[1,2], [3,4], [5,6]];

(async () => {
  for (const batch of batchedIds) {
    const response = await Promise.all(batch.map(id => {
      return slowAsync(id);
    }));
    console.log(response);
  }
})();

@Trincot 一言以蔽之!

进一步说明:除了使用函数闭包,您还可以使用 Function.prototype.bind() 将每个批次的单个 id 绑定到 setTimeout() 回调函数,如图所示以下:

const batchedIds = [[1,2], [3,4], [5,6],[7,8,9,10]];

(async () => {
  for (const batch of batchedIds) {
    console.log(await Promise.all(batch.map(id=>new Promise(r=>setTimeout(r.bind(null,id),1000)))));
  }
})();