如何正确实现和使用承诺/异步函数集合的分块和批处理? [已关闭]

问题描述 投票:0回答:2

在批量处理大量异步函数时,我面临两种情况:

  1. 收集所有异步函数:
import { chunk } from "lodash";

const func = async () =>
  new Promise((resolve) => {
    const data = [...Array(500000).keys()];
    data.find((d) => d === Math.floor(Math.random() * 50000));
    resolve("resolved");
  });
const start = Date.now();
const promises = Array.from({ length: 100 }).map((_i) => func());

const chunkedPromises = chunk(promises, 25);
for (const batchedPromises of chunkedPromises) {
  await Promise.allSettled(batchedPromises);
}
console.log("Time taken: ", Date.now() - start);

(当推送到集合时开始执行),然后发送到一个方法,该方法将这些分块到一批异步函数中,并执行

await Promise.allSettled(batchedPromises)
并整理每批结果!

  1. 收集对所有异步函数的引用:
import { chunk } from "lodash";

const func = async () =>
  new Promise((resolve) => {
    const data = [...Array(500000).keys()];
    data.find((d) => d === Math.floor(Math.random() * 50000));
    resolve("resolved");
  });
const start = Date.now();
const asyncFuncs = Array.from({ length: 100 }).map((_i) => () => func());

const chunkedFuncs = chunk(asyncFuncs, 25);

for (const batchedFuncs of chunkedFuncs) {
  await Promise.allSettled(batchedFuncs.map((fn) => fn()));
}
console.log("Time taken: ", Date.now() - start);

然后将它们发送到一个方法,该方法将批处理引用并执行

await Promise.allSettled(batchedFuncs.map(fn => fn()))
并整理每批结果!

注意

func
仅用于演示目的。它可以是任何现实世界的
asnyc
函数。

nodejs 如何执行上述两个场景?

您会使用选项 1 吗?如果是,为什么?

您何时会使用选项 2?为什么?

javascript node.js async-await scheduling promise.all
2个回答
1
投票

以上哪一项(如果有的话)是批处理异步函数集合的正确方法,为什么?

绝对是第二个。

正如您自己所指出的,在第一种方法中,当您将承诺推送到集合中时(特别是当您在

getAsyncFunction()
期间调用
map
时),所有函数都已经开始执行。没有进行实际的批处理执行。这样做的唯一目的是创建一个 发生错误时导致应用程序崩溃的危险,因为您正在创建承诺(可能会拒绝)而没有立即附加错误处理程序。

但即使在你的第二个代码片段中,术语也很混乱。当调用它而不是异步函数时,

getAsyncFunction
会为您提供一个承诺,并且
promises
是一个异步函数数组,而不是一个承诺数组(
chunkedPromises
batchedPromises
也是如此)。是的,命名事物很困难,但重要的是要精确,至少在值的类型上要精确,以避免使可能需要阅读代码的其他程序员(以及未来的你)感到困惑。


-1
投票

编辑:

截至您上次编辑时,您的选项 2 将花费 4 倍的时间。没有合理的理由将选项 1 中的内容分块,js 将在主代码块终止时执行所有内容,您一次只需解析 25 个。

第二个选项在分块方面更有意义(在前 25 个完成之前不会启动接下来的 25 个),对于在每个承诺中发出请求以不超出允许的同时服务器连接或以其他方式管理负载可能很有用。例如在 js 中,以避免 js 生命周期(帧)之间的滞后。

旧答案:

在这种情况下,没有明确的正确或错误的做事方式,这取决于具体的用例以及什么更有意义或更具可读性。 在其他支持

多线程

的语言中,它可能会产生巨大的差异。您希望尽快开始每个流程,因为当您开始最后一个流程时,大多数流程可能已经完成。然而,在 Javascript 中,不会有可测量的差异,因为即使是异步的,你的 Promise 也不会与你的主线程并行运行。相反,它们将在主代码块终止后执行(对于 Javascript 和 NodeJS 都是如此)。 在性能或功能方面,您的选择基本相同,这取决于偏好以及最适合您的情况。

© www.soinside.com 2019 - 2024. All rights reserved.