gpt4 book ai didi

javascript - 什么都不等?使用空等待分解大型同步函数

转载 作者:行者123 更新时间:2023-11-30 11:02:06 25 4
gpt4 key购买 nike

我有一个相当简单的问题,但我找不到答案。

我有一个名为 foo 的异步函数,它从不等待,所以它是同步运行的。 foo 中是一个长时间运行的循环,它将大量数据插入中间缓冲区。有一个使用 RxJS 的异步操作将从该缓冲区中提取和处理数据,但它不会执行,直到我的长时间运行的循环以某种方式产生,或者当循环完全完成将数百万个数据点推送到中间缓冲区时(不好).

我可以 await undefined 或一个虚拟值,以便 foo 可以屈服于正在等待的事件吗?还是 promise 会立即返回,因为它会立即用一个虚拟值解析,并且该函数不会产生?

最佳答案

如果你有一段长时间运行的同步代码,你想为其他事情产生更多 yield ,在 node.js 中有很多方法可以解决这个问题,每种方法都有自己的优点/缺点:

  1. 将长时间运行的同步代码移至另一个 node.js 进程,并将完成情况传回主进程。如果你真的希望你的长时间运行的同步代码完全不干扰你的 node.js 代码正在做的事情,这是最清晰的方法。如果您定期运行此代码或从多个请求中运行它,您甚至可以创建一个工作队列和多个其他进程来运行这些任务。从事图像识别或其他复杂数据分析等耗时工作的人都希望将耗时代码完全从主 node.js 事件循环中取出。

  2. 使用 node.js 中的新 Workers 将这个长时间运行的同步代码移出主循环。这会带来一些限制,因为工作人员几乎必须独立(有点像浏览器中的 webWorkers)并通过消息与主线程通信。

  3. 将您的同步代码分成小的工作单元,并在计时器滴答时执行每个单元。这允许事件循环在您的工作单元之间运行其他任务。这通常是重写代码的大量工作,因为您本质上必须创建某种状态机,并且必须将处理分解为足够小的工作单元,以便您可以执行一个工作单元,将状态完全保存为某种类型对象,退出,让 node.js 做一些其他的事情,然后在某种计时器上被调用以执行另一个工作单元。您也可以以某种方式为此使用 promises/await,但 promises 具有更高的优先级,因此您可能仍然需要 node.js 代码中的一些其他操作。工作单元也可以在调用生成器时执行,其中状态可以保存在生成​​器函数中。

在大多数情况下,如果您选择选项 #1 或 #2,则代码重写量最少,尽管您并没有真正分享实际代码的作用,以便我们自己在这方面提供意见。而且,只有 #1 和 #2 真正让长时间运行的 CPU 工作脱离了主 node.js 线程。选项 #3,无论是使用计时器还是使用 promise,都只允许与其他任务进行更多交错,但 CPU 仍然经常因同步工作而陷入困境。

Can I await undefined or a dummy value, so that foo can yield to events that are waiting?

有点。 Promise .then() 处理程序以比事件循环中的所有事件更高的优先级运行,因此使用 await 来 yield 将允许事件循环中的其他一些事情运行(像其他挂起的 .then() 处理程序一样)但不允许所有其他事情运行(如挂起的计时器)。因此,我真的不建议在某个常量上插入 await 作为事件循环中所有事物之间“公平”调度的解决方案,因为它不会实现这一点。它将允许一些(但不是全部)其他事情与您的工作交织在一起。

仅供引用,您可以通过设置 await、await 计时器来允许其他计时器运行,例如本例中的计时器,但您还必须测试事件循环中的所有其他类型的事物(网络、磁盘 I/O, etc...) 看看它是否允许它们运行:

    function delay(t) {
return new Promise(resolve => {
setTimeout(resolve, t);
});
}

let start = Date.now();

// long running function
async function run() {
let i = 0;
let y;
while(i++ < 1000000000) {
for (let t = 0; t < 100; t++) {
let x = 20;
y = Math.pow(x,i);
}
await delay(1);
}
return i;
}

run();

setInterval(() => {
let delta = Date.now() - start;
console.log((delta/1000).toFixed(3));
}, 50);

我的建议仍然是上面的选项 #1 或 #2,让另一个线程/进程参与你的长时间运行操作,因为这对 node.js 来说总是更好。

关于javascript - 什么都不等?使用空等待分解大型同步函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57300969/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com