NodeJS Promise all 从任务队列中获取所有承诺
NodeJS Promise all take all promises from task queue
我正在尝试创建一个函数,该函数将获取承诺数组并分块执行它们。
这里有一个我编写的函数示例,它应该可以实现我想要的功能。
但是发生的事情是所有的承诺都在第一个 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 并没有真正接受你给他的东西,而是所有在任务队列中的 Promise任务队列
有人知道如何处理这类问题吗?
编辑:我发现客户端的工作方式相同...
这里有三个方面,分块 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);
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')
);
我正在尝试创建一个函数,该函数将获取承诺数组并分块执行它们。
这里有一个我编写的函数示例,它应该可以实现我想要的功能。 但是发生的事情是所有的承诺都在第一个 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 并没有真正接受你给他的东西,而是所有在任务队列中的 Promise任务队列
有人知道如何处理这类问题吗?
编辑:我发现客户端的工作方式相同...
这里有三个方面,分块 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);
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')
);