【发布时间】:2020-09-22 03:30:48
【问题描述】:
有两个异步函数。一个会设置一个变量,另一个会等待变量改变,如下面的代码所示。即使通常的做法是使用 事件或承诺,在我的情况下是不可行的。
function delay(ms: number): Promise<void> {
return new Promise(resolve => {
setTimeout(() => { resolve(); }, ms);
});
}
function async fn1() {
let done = false;
(async () => {
await delay(100); // simulate some work
done = true;
})();
await (async () => {
while (!done) { }
// do other things
})();
}
function async fn2() {
let done = false;
(async () => {
await delay(100); // simulate some work
done = true;
})();
await (async () => {
while (!done) {
await delay(200); // introduce some extra delay
}
// do other things
})();
}
我想知道为什么fn1 会卡在while 循环中,但fn2 会起作用。
因为它们之间的唯一区别是后者
引入了一些额外的等待。这是否与一些潜在的
NodeJS/V8解释器的线程调度机制?
我使用的是 Node 12.18.3 和 TypeScript 4.0.3。
编辑:修正fn2 的定义。
【问题讨论】:
-
在
while (!done) { } // do other things }运行期间,除非done在do other things中设置为true,否则不会执行其他任何操作...因为调用堆栈永远不会为空 -
基本上 js 是单线程的,如果有什么东西让它像你的忙循环一样被阻塞,它不能去其他工作,除非它暂停
-
查找 javascript 事件队列或 javascript 调用堆栈,以很好地解释这一切在 JS 中是如何工作的
-
您知道,对于像 nodejs 这样的事件驱动的单线程环境来说,繁忙的等待循环通常是错误的设计类型。有时可以使它们与 Promise 和
await一起工作,但即便如此,最好还是使用一个在事件发生时解决的 Promise 并在没有任何繁忙等待循环的情况下监听它。如果我们看到的是真实的、实际的代码,而不是这个实际上并没有做任何有用的事情并且不是现实世界问题的伪代码,我们可以通过一个好的设计更好地帮助您。 -
所以,总而言之,这是一条错误的设计路径。向我们展示一个真实世界的问题(不是伪代码),我们将帮助您以正确的方式设计该实际问题。
标签: javascript node.js