【问题标题】:NodeJS Promise all take all promises from task queueNodeJS Promise 全部从任务队列中获取所有 Promise
【发布时间】:2021-04-24 20:01:35
【问题描述】:

我正在尝试创建一个函数,该函数将获得一个承诺数组并将它们分块执行。

这里我有一个我写的函数的例子,它应该已经完成​​了我想要的。 但是发生的事情是所有的承诺都已经在第一个 promise.all 之后执行了。 nodeJS 调试器显示它按我希望的那样工作。但我可以在 whireshark 中看到所有请求都是在第一个块之后发送的。

const reqs = [...Array(10)].map(() => () => axios.post('http://localhost:7000/test', {}))


const handleChunks = (reqs) => {
    const chunks = []
    const chunkSize = 5
    for (let i = 0; i < reqs.length; i += chunkSize) {
      chunks.push(reqs.slice(i, i + chunkSize))
    }
    chunks.reduce(async (acc, chunk) => {
      const chunkToPromise = chunk.map((chunkFunc) => chunkFunc())
      return Promise.all(chunkToPromise).then(async (result) => {
          acc = await acc
          acc.push(result)
          return acc
      })
    }, Promise.resolve([]))
}

在我看来,我创建的所有 Promise 都已经在任务队列中声明了自己,并且 Promise.all 并没有真正接受你给他的东西,而是任务队列中的所有承诺

有没有人知道如何处理这种问题?

编辑:我发现在客户端上的工作方式相同......

【问题讨论】:

  • 您对问题的描述与您发布的代码非常不同,这使得它很难理解。特别是,您的数组切片是否按照您预期的方式工作,或者您希望通过分块来完成的工作(不是向服务器发送一堆请求?),这一点都不清楚。 “任务队列”是什么意思,因为我没有看到你,例如从堆栈中弹出任何东西?
  • 我能解释的最好的问题是您想向服务器发出 n 请求,但希望一次运行它们不超过 k 请求,等待当前的一组k 请求在继续下一个之前完成。对吗?
  • 是的,Jared 你是对的.. 抱歉,如果我不够清楚。

标签: javascript node.js promise async-await chunks


【解决方案1】:

这里有三个方面,将 Promise 分块,运行块,并等待它们全部完成。让我们创建一些助手:

// NOTE: works but probably not optimal. I fired this off the top of my head,
// for something like this in production I'd use a library function from
// lodash or ramda or something.
const partition = (n, xs) => {
  const results = [];
  let i = k = 0;
  while (i < xs.length) {
    results.push([]);
    while (k < n) {
      if (i === xs.length) break;
      results[results.length - 1].push(xs[i]);
      i++;
      k++;
    }
    k = 0;
  }
  return results; 
};

// This will make the requests from the passed in array and
// wait for them all to finish. Note that unlike Promise.all
// allSettled will not bail early if you get a rejection.
const runPromiseFns = async (ps) => Promise.allSettled(ps.map(x => x()));

// This will take an array of arrays of Promise generating functions
// and wait for each sub-array to settle before moving on
// to the next one.
const runChunks = async (chunks) => {
  for (let chunk of chunks) {
    await runPromiseFns(chunk);
  }

  return;
};

太好了。现在:

// Array of request thunks from your original code
const reqs = [...Array(10)].map(() => () => axios.post('http://localhost:7000/test', {}));

// Break into chunks of 5
const chunks = partition(5, reqs);

// Run through the execution pipe. Here allDone is a
// Promise you can .then or await somewhere else.
const allDone = runChunks(chunks);

【讨论】:

  • Jared 首先感谢您的快速回复。看起来您的解决方案正在运行。但它在我的环境中不起作用。
  • 经过几次实验,我发现我的环境中的问题是我使用的是 NODE js 版本 10.14 -> 这个版本似乎有一个错误。我在 12+ 版本中尝试了相同的代码,它运行良好
【解决方案2】:
const promiseAllFn = (pollingRequests) => Promise.all(pollingRequests.map((pollingRequest) => callApi(pollingRequest)));

    chunk(Object.values(subRegister), 4).reduce(
        (prev, pollingRequests) => prev.then(() => promiseAllFn(pollingRequests)),
        Promise.resolve('start')
    );

【讨论】:

    猜你喜欢
    • 2019-03-27
    • 1970-01-01
    • 2017-11-28
    • 2022-10-06
    • 2021-04-24
    • 2020-08-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多