我们如何阻止事件循环?

How can we block event loop?

我研究过Node.Js中的事件循环,它以异步和非阻塞的方式处理请求。有什么办法可以阻止事件循环的执行吗?

有很多方法可以阻止事件循环。有些方法只是暂时阻止它(比如使用同步文件 I/O),有些方法会永远阻止它。

例如,这将永远阻止它:

let flag = false;
setTimeout(() => {
    // this callback never gets called
    // because event loop is blocked
    flag = true;
}, 1000);

while (!flag) {
    console.log("still waiting")
}
// never get here

问题是 while() 循环一直运行到 flag 更改值。只要while循环是运行,事件循环就被阻塞了。有一个 setTimeout() 想要在 1 秒内触发,但在解释器返回到事件循环之前它实际上不能调用它的回调。但是,在 while() 循环完成之前,它不会返回到事件循环。这是一个导致无限循环的死锁,事件循环被永久阻塞。

while 循环完成之前,setTimeout() 无法调用其回调,并且在 setTimeout() 运行其回调之前,while 循环不会结束。死锁,无限循环。


这会在所有文件操作和所有文件处理过程中阻塞它一段时间:

setTimeout(() => {
    // this doesn't get to run until all the synchronous file I/O 
    // finishes in the code below, even though the timer is set
    // for only 10ms
    console.log("finally got to run the timer callback");
}, 10);

let files = some array of files;
for (let file of files) {
    let data = fs.readFileSync(file);
    let lines = data.split("\n");
    for (let line of lines) {
        // do something
    }
}

事件循环在线程上运行,因此任何阻塞线程的调用(如无限循环、同步文件操作或阻塞网络调用)都会阻塞事件循环。

你可以把事件循环想象成先进先出的回调队列,如果一个函数调用卡住了,后续的调用会等待它完成。

您还可以通过使用 setTimeout 或 setInterval 函数将新任务无限排队到末尾来阻止事件循环。