使用Promise.all时承诺之间的延迟

时间:2017-11-21 18:08:35

标签: ecmascript-6 promise

有没有办法使用Promise.all()来延迟对promise数组的求值?

在将延迟函数添加到数组之前手动添加延迟函数是否有意义?

Promise.all([p1,p2,p3]).then(res => console.log(res))

我想添加延迟,因为我的服务器不能同时处理太多请求。

5 个答案:

答案 0 :(得分:2)

Promise.all旨在解决何时履行承诺,但无论Promise.all如何,都会评估现有承诺。

为此,应首先创建承诺以产生延迟:

const delayIncrement = 500;
let delay = 0;

const p1 = new Promise(resolve => setTimeout(resolve, delay)).then(() => fetch(...));

delay += delayIncrement;

const p2 = new Promise(resolve => setTimeout(resolve, delay)).then(() => fetch(...));

delay += delayIncrement;

...
Promise.all([p1,p2,p3]).then(...);

可以使用相同的解决方案在循环内批量创建请求承诺。

延迟承诺的食谱可以在this answer中找到。

答案 1 :(得分:1)

  

有没有办法延迟使用的延迟评估一组承诺   Promise.all()

没有。承诺没有“评估”,他们只是解决。当这种情况发生时,由他们的创造者决定,没有别的。调用Promise.all后,已经创建了承诺p1p2p3(并且可能已经启动了异步任务)。

答案 2 :(得分:0)

是的,您 可以 使用Promise.all延迟诺言以创建交错执行,这很容易做到:

// Promise.all() with delays for each promise
let tasks = [];
for (let i = 0; i < 10; i++) {
  const delay = 500 * i;
  tasks.push(new Promise(async function(resolve) {
    // the timer/delay
    await new Promise(res => setTimeout(res, delay));

    // the promise you want delayed
    // (for example):
    // let result = await axios.get(...);
    let result = await new Promise(r => {
      console.log("I'm the delayed promise...maybe an API call!");
      r(delay); //result is delay ms for demo purposes
    });

    //resolve outer/original promise with result
    resolve(result);
  }));
}

let results = Promise.all(tasks).then(results => {
  console.log('results: ' + results);
});

您也可以https://github.com/comm1x/ktor-boot/blob/master/test/common/common.kt运行它。

而不是链之间的延迟(可以通过.then()来完成,如其他答案所示),这是每个Promise都不同的延迟,因此当您调用Promise.all()时,它们将错开。例如,当您以某个速率限制调用API时,如果您通过并行触发所有调用来违反该速率限制,此功能将非常有用。

和平

答案 3 :(得分:0)

我需要动态创建呼叫,因此基于@ estus-flask的回答,设法提出了建议:

  let delay = 0; const delayIncrement = 1000;

  const promises = items.map(item => {
    delay += delayIncrement;
    return new Promise(resolve => setTimeout(resolve, delay)).then(() =>
        fetch(...);
  })

  let results = await Promise.all(promises);

答案 4 :(得分:0)

另一种方法是劫持循环的转译方式:

async function doABatchOfAsyncWork(workItems) {
  for (const item of workItems) {
    await workTask(item)
    await delay(1000) // not built-in but easily implemented with setTimeout + promise
  }
}

当然,您也可以保存值并在最后返回它们,就像您通常在 for 循环中所做的那样。你不能用 map 来做这件事,因为 await 必须在传入的 map-functor 的异步上下文中。如果你使用 map 它会同时执行所有内容,最后延迟 1s。