我正在从this site.学习节点js回调和异步行为。在给出的示例中,我编写了以下代码以更好地理解它。
function callbackTester (callbackFn){
console.log('From callback tester.');
callbackFn();
}
function pollingWait(){
while (true) {}
}
callbackTester(() => {
console.log('From anonymous function.');
setTimeout(()=>{
console.log("I'm waiting!");
}, 500);
// pollingWait();
});
console.log('I am the last one');
现在,当我注释掉pollingWait()
函数时,它可以正常工作。它给出以下输出:
From callback tester.
From anonymous function.
I am the last one
I'm waiting!
现在,当我注释掉setTimeout
函数并添加pollingWait()
时,程序进入无限循环。我认为这也是预期的行为,因为节点js是单线程的,无法避免无限循环。那么这种异步行为是如何在后台运行的呢?
如何决定何时继续执行以及何时不继续执行?是否可以使自己的函数像setTimeout
一样异步使用?
答案 0 :(得分:2)
我认为这也是一种预期的行为,因为节点js是单线程的并且无法避免无限循环。
Node.js isn't single-threaded anymore,但是只有一个主线程,除非您创建工作线程。
那么这种异步行为是如何在后台运行的?
Node.js的主线程在一个循环上工作:您的顶级代码运行并返回,然后所有排队的操作(例如计时器回调)都运行并返回,然后下一个排队的操作运行并返回,等等。 setTimeout
的工作方式如下:当计时器触发时,事件循环会看到该事件,并将对计时器回调的调用排队。另请注意,虽然默认情况下Node.js只有一个主JavaScript线程,但这并不意味着Node本身是单线程的。特别是它可能在另一个内部线程上执行I / O处理。
是否可以使自己的函数像setTimeout一样异步工作?
仅通过使用已提供异步行为并将其包装的东西。其中包括:
setTimeout
setImmediate
process.nextTick
then
或catch
回调乍一看,您可能会认为async
函数会这样做,但实际上并没有:async
函数中的代码一直同步运行 直到第一次它等待一个承诺解决方案(或者直到它返回)。因此,异步性实际上与上面的最后一个要点相同:then
或catch
回调。
您不能所做的事情(没有工作线程)就像pollingWait
那样忙于等待,因为在忙于等待的线程上什么也不会发生
答案 1 :(得分:0)
尝试一下:
let done = false;
setTimeout(() => {
done = true
}, 5);
const eventLoopQueue = () => {
return new Promise(resolve =>
setImmediate(() => {
console.log('event loop');
resolve();
})
);
}
const run = async () => {
while (!done) {
console.log('loop');
await eventLoopQueue();
}
}
run().then(() => console.log('Done'));