Promise.all()有限制吗?

时间:2016-11-02 08:40:38

标签: javascript es6-promise

是否有实现let res = Promise.all([...p], limit)的方法/模式?

  • promise-array包含构造和返回promise的函数
  • 在所有res结算之后,
  • p应该得到解决
  • 只有limit=3承诺应在并行
  • 中运行
  • n + 1承诺应在n完成后立即开始。因此,总有limit个解析器并行运行。

特别是最后一点让我头疼。

我目前的解决方案是将promises-array拆分为limit大小的块并链接它们。这里的缺点是第二组不会开始,直到第1组的所有Promise都已解决。

3 个答案:

答案 0 :(得分:3)

我提出了创建n = limit链的想法,这些链并行运行并且只要有承诺就附加:

let promises = [];
for(let i=0; i<11; i++) promises[i] = () => {
  console.log('Construct:',i);
  return new Promise(resolve => {
    setTimeout(function() {
      console.log('Resolve:',i);
      resolve(i);
    }, Math.round(Math.random() * (2000 - 500) + 2000));
  });
}


function parallelLimit(promiseFactories, limit) {
  let result = [];
  let cnt = 0;

  function chain(promiseFactories) {
    if(!promiseFactories.length) return;
    let i = cnt++; // preserve order in result
    return promiseFactories.shift()().then((res) => {
      result[i] = res; // save result
      return chain(promiseFactories); // append next promise
    });
  }

  let arrChains = [];
  while(limit-- > 0 && promiseFactories.length > 0) {
    // create `limit` chains which run in parallel
    arrChains.push(chain(promiseFactories));
  }

  // return when all arrChains are finished
  return Promise.all(arrChains).then(() => result);
}


parallelLimit(promises, 4).then(console.log);

很高兴阅读您的意见和建议:)

答案 1 :(得分:1)

bluebird-as扩展程序中的sequenceWithParallelism功能似乎专为您想要的功能而设计。如上所述,它使用bluebird进行实现,但我在sequenceWithParallelism函数的实际内容中没有看到任何蓝鸟特定的内容,因此您可以摘录该函数并在您自己的代码中使用它,如:

sequenceWithParallelism(limit, f => f())([..p])
    .then(function () {

    });

奇怪的是,这个功能似乎并不是为了解决所有承诺的结果,所以如果你需要,你可能需要做一些调整。

答案 2 :(得分:0)

我最终编写了以下代码:

const parallelLimit = (asyncFuncs, limit) => {
  return new Promise((res, rej) => {
    let open = 0
    const rets = [], errs = []
    const exec = () => { while(ff.length && open < limit) ff.shift()() }
    const ff = asyncFuncs.map(f => {
      return () => {
        open++
        f()
          .then(r => rets.push(r))
          .catch(e => errs.push(e))
          .finally(_ => {
            open--
            exec()
            if(!ff.length && !open)
              return errs.length ? rej(errs) : res(rets)
        })
      }
    })
    exec()
  })
}

// test:

const t = Date.now()
const funcs = [...Array(10).keys()].map(idx => {
  return () => {
    return new Promise((res, rej) => {
      setTimeout(() => {
        console.log(`idx: ${idx} time: ${Date.now() - t}`)
        res(idx)
      }, 1000)
    })
  }
})

parallelLimit(funcs, 2)
  .then(res => console.log(`then ${res.join(',')}`))
  .catch(errs => console.log(`catch ${errs.join(',')}`))