简体   繁体   English

在Node.js中,setTimeout()是否会阻止事件循环?

[英]In Node.js, does setTimeout() block the event loop?

If I have a simple setTimeout() function, and set it for 10 seconds... 如果我有一个简单的setTimeout()函数,并将其设置为10秒钟...

The the entire server is dead inside those 10 seconds??? 整个服务器在那10秒之内都死了??? Is this true? 这是真的? That's what I heard. 这就是我所听到的。

The answer is no . 答案是否定的 What your link Node.js: How would you recreate the 'setTimeout' function without it blocking the event loop? 您的链接是什么Node.js:如何在不阻止事件循环的情况下重新创建“ setTimeout”函数? showed was not a setTimeout blocking the event loop it was a while loop that deliberately blocks the event loop. 显示的不是setTimeout阻止事件循环,而是while循环故意阻止了事件循环。 If you want your server to be fast you do not want to block the event loop. 如果希望服务器速度更快,则不要阻塞事件循环。 An asynchronous callback such as setTimeout will work great. 诸如setTimeout类的异步回调将非常setTimeout

Are you trying to block for some reason (like testing or something?) 您是否出于某种原因(例如测试或其他原因)尝试阻止?

Another finding that may help others who are learning Node.js and curious of this question, but tricked by a hidden behavior of modern browsers. 另一个发现可能会帮助正在学习Node.js并对这个问题感到好奇的其他人,但被现代浏览器的隐藏行为所欺骗。

The code is really simple, I just want to test my understanding of the "async nature" of Node.js. 代码真的很简单,我只想测试我对Node.js的“异步性质”的理解。

var express = require('express');
var router = express.Router();

router.get('/', function(req, res, next) {
    console.log("route begin");
    var start = new Date();


    setTimeout(function() {
        res.render('index', { title: start + ' - ' + new Date()});
    }, 20000);//force delay of 20 seconds.

    console.log("route end");
});

module.exports = router;

If I start three browser windows(Firefox, more accurately), open the URL defined by this route at the same time, and check the console log from Node.js, it is clear the request is not handled concurrently ! 如果我启动三个浏览器窗口(更准确地说是Firefox),同时打开此路由定义的URL,然后从Node.js检查控制台日志,很明显,请求不是同时处理的

I tried the test several times, the results are same. 我尝试了几次测试,结果是一样的。

The typical log output is like this: 典型的日志输出如下所示:

route begin at: Fri Aug 28 2015 18:35:57 GMT+0800 (CST)
route end at: Fri Aug 28 2015 18:35:57 GMT+0800 (CST)
route begin at: Fri Aug 28 2015 18:36:18 GMT+0800 (CST)
route end at: Fri Aug 28 2015 18:36:18 GMT+0800 (CST)
route begin at: Fri Aug 28 2015 18:36:20 GMT+0800 (CST)
route end at: Fri Aug 28 2015 18:36:20 GMT+0800 (CST)

And also, strangely, it was not running in serial mode either(if Node.js is blocked by setTimeout, it should). 而且,奇怪的是,它也没有以串行模式运行(如果Node.js被setTimeout阻止了,它应该)。 The interval between the first and second request is 20 seconds, but the second and the third is just 2 seconds. 第一个请求和第二个请求之间的间隔为20秒,但是第二个和第三个请求之间的间隔仅为2秒。

After scratching my head for quite a while, I suddenly recall that the browser has a connection limit on the same host ! 挠挠了一段时间后,我突然想起浏览器在同一主机上有连接限制

So, I quickly setup another test, but this time by issuing multiple curl commands instead. 因此,我快速设置了另一个测试,但是这次是通过发出多个curl命令。

Hallelujah! 哈利路亚!

route begin at: Fri Aug 28 2015 18:42:51 GMT+0800 (CST)
route end at: Fri Aug 28 2015 18:42:51 GMT+0800 (CST)
route begin at: Fri Aug 28 2015 18:42:53 GMT+0800 (CST)
route end at: Fri Aug 28 2015 18:42:53 GMT+0800 (CST)
route begin at: Fri Aug 28 2015 18:42:55 GMT+0800 (CST)
route end at: Fri Aug 28 2015 18:42:55 GMT+0800 (CST)

That is not true. 那是不对的。 When you call setTimeout and return out of your code the server is not blocked. 当您调用setTimeout并返回代码时,服务器不会被阻止。 It is free to process other events (possibly other setTimeout callbacks) while waiting for your particular timer to fire 在等待特定计时器触发时,可以自由处理其他事件(可能是其他setTimeout回调)

The link which you seem to be confused about does not state that setTimeout will block. 您似乎感到困惑的链接没有说明setTimeout将被阻止。 Rather, the OP in that question was trying to make a custom function called wait that would behave like setTimeout . 相反,该问题中的OP试图创建一个名为wait的自定义函数,其行为类似于setTimeout The wait function is the blocking function - setTimeout will not block. wait功能是阻止功能setTimeout将不会阻止。

The main process seems to be monothreaded by host and blocked by a setTimeout or a while . 主进程似乎由主机单线程处理,并被setTimeoutwhile阻塞。

However, there is an alternative with this code which works as expected and don't block the main process or the event loop: 但是,此代码还有一种替代方法,可以按预期工作,并且不会阻塞主进程或事件循环:

var express = require('express')
var app = express()

function setTimeoutAsync (callback, time) {
  setTimeout(function () {
    callback()
  }, time)
  return 0
}

app.get('/', function (req, res, next) {
    console.log("route begin")
    var start = +new Date()
    setTimeoutAsync(function () {
      console.log("route done")
      res.json({ delay: ((+new Date()) - start) + 'ms' })
    }, 5000)
    console.log("route end")
});

app.listen(8000) 

In terminal : 在终端:

route begin // first page
route end
route begin // second page
route end
route begin // third page
route end
route done // first render
route done // second render
route done // third render

Good sources: 好的来源:

https://www.journaldev.com/7462/node-js-architecture-single-threaded-event-loop https://www.journaldev.com/7462/node-js-architecture-single-threaded-event-loop

https://nodejs.org/en/docs/guides/blocking-vs-non-blocking/ https://nodejs.org/en/docs/guides/blocking-vs-non-blocking/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM