Javascript Nodejs异步循环正在阻止React UI呈现
我有一个电子应用程序,需要通过UDP发送大量数据。这个过程是通过点击我的React UI中的一个按钮开始的,这个例子简化了我的问题。我的反应按钮:Javascript Nodejs异步循环正在阻止React UI呈现,javascript,node.js,reactjs,asynchronous,electron,Javascript,Node.js,Reactjs,Asynchronous,Electron,我有一个电子应用程序,需要通过UDP发送大量数据。这个过程是通过点击我的React UI中的一个按钮开始的,这个例子简化了我的问题。我的反应按钮: <button onClick={() => { foo(); }} > Run foo </button>; 虽然foo是异步的,但它仍然冻结了React UI 由于JavaScript是单线程的,所以只要调用无限while循环异步函数,它就会阻塞线程。您可以通过在while循环中引入wait来解
<button
onClick={() => {
foo();
}}
>
Run foo
</button>;
虽然foo是异步的,但它仍然冻结了React UI 由于JavaScript是单线程的,所以只要调用无限while循环异步函数,它就会阻塞线程。您可以通过在while循环中引入
wait
来解决这个问题,这将允许您的程序返回到执行代码的其他部分
export const foo = async () => {
while (true) {
await new Promise(resolve => {
resolve();
});
}
};
async
函数在执行时仍然会阻塞主(也是唯一)线程<代码>异步函数通常会有所帮助,因为它们调用的库函数实际上释放了主线程
例如,如果您没有执行简单的无限循环,而是执行以下操作:
function timeout(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
function yieldThread() {
return new Promise(resolve => resolve());
}
export const foo = async () => {
while (true) {
console.log("hello");
await timeout(2000);
//or
await yieldThread();
}
};
export const foo = async () => {
while (true) {
const packet = getPacket();
await new Promise(resolve => {
sendUdp(packet, resolve);
});
}
};
你的主线程不会被阻塞
当然,timeout
或简单的yield
通常不是处理这种情况的正确方法,但它应该举例说明典型的结构
假设您有一个函数sendUdp(packet,callback)
,该函数的第一个参数是数据包
当完成发送后,您需要发送并作为第二个不带参数的回调,
你可以这样做:
function timeout(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
function yieldThread() {
return new Promise(resolve => resolve());
}
export const foo = async () => {
while (true) {
console.log("hello");
await timeout(2000);
//or
await yieldThread();
}
};
export const foo = async () => {
while (true) {
const packet = getPacket();
await new Promise(resolve => {
sendUdp(packet, resolve);
});
}
};
JavaScript在单个线程中运行。即使函数是异步的,如果应用程序运行无限while循环,它仍然会阻止应用程序。异步函数只是一个返回承诺的函数。它没有说明您在函数中或承诺中所做的事情是异步的。您编写了一个spinloop,无论线程在哪里运行,它都会阻塞线程。
异步函数
(或通常的承诺)不会使事情在不同的线程中运行。要做到这一点,您需要使用一个worker。是的@Bergi,我一直在考虑使用一个worker,因为这将允许我创建一个新线程,这将是我在任何其他语言中的解决方案。虽然Nodejs的工人让我很困惑。。。不是说nodejs作为一个整体不会让我感到困惑,你能分享更多关于“我需要通过UDP发送大量数据”的细节(也许还有代码)吗?一般来说,解决方案不是在同步while(true)
循环中这样做,而是成批地对它们进行批处理,以使它们之间存在延迟,和/或使用异步操作系统功能等待网络缓冲区实际发送数据包。使用foo
的示例定义仍然会阻止UI。尝试您的示例,使用yieldThread
,仍然会冻结UI。@asd12tgzxvbgt是否完全冻结?例如,如果您尝试使用超时示例,它是否有效?在这种情况下,很简单,您触发了很多请求,这导致主线程过载,您应该对请求进行速率限制。请注意,在节点中,API支持同时发送多个数据包YUP完全冻结。有趣的是,我创建了一个名为foo
的函数,它记录控制台,然后调用setTimeout(foo,0)代码>。这在没有冻结UI的情况下工作了一段时间。后来,我将代码实现为foo
,它再次冻结。为了找到问题,我删除了越来越多的代码,但当我回到使用setTimeout(foo,0)
的示例时,它仍然冻结了!这不是很疯狂吗?@asd12tgzxvbgt如果没有手动尝试的代码,我猜您正在淹没事件循环;虽然您确实没有从技术上阻塞主线程,但您仍然将几乎所有的时间都花在foo
函数上,UI冻结。你应该增加一些延迟;例如,在测试中,不是setTimeout(foo,0)
而是setTimeout(foo,delay)
其中delay
有时至少大于0