在Node.js中,setTimeout()阻塞事件循环吗?

时间:2012-01-21 05:43:42

标签: javascript node.js

如果我有一个简单的setTimeout()函数,并将其设置为10秒......

整个服务器在那10秒钟内死了???这是真的?这就是我所听到的。

5 个答案:

答案 0 :(得分:21)

答案是。您的链接Node.js: How would you recreate the 'setTimeout' function without it blocking the event loop?显示的不是setTimeout阻止事件循环,而是{strong>故意阻止事件循环的while循环。如果您希望服务器速度很快,则不希望阻止事件循环。诸如setTimeout之类的异步回调将非常有用。

您是否因某种原因(例如测试或其他原因)试图阻止?)

答案 1 :(得分:6)

另一个发现可能有助于其他正在学习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;

如果我启动三个浏览器窗口(Firefox,更准确),同时打开此路由定义的URL,并从Node.js检查控制台日志,很明显请求不会同时处理

我尝试了几次测试,结果是一样的。

典型的日志输出如下:

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)

而且,奇怪的是,它也没有以串行模式运行(如果Node.js被setTimeout阻止,它应该)。第一个和第二个请求之间的间隔是20秒,但第二个和第三个请求之间的间隔仅为2秒。

在我挠了头很长一段时间之后,我突然想起浏览器在同一主机上有连接限制

所以,我快速设置了另一个测试,但这次通过发出多个curl命令。

哈利路亚!

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)

答案 2 :(得分:2)

事实并非如此。当您致电setTimeout并退回代码时,服务器不会被阻止。在等待特定计时器触发时可以自由处理其他事件(可能还有其他setTimeout回调)

答案 3 :(得分:2)

您似乎感到困惑的链接表明setTimeout会阻止。相反,该问题中的OP试图创建一个名为wait的自定义函数,其行为类似于setTimeoutwait函数是阻塞函数 - setTimeout不会阻止。

答案 4 :(得分:1)

主要过程似乎由主持人单线化,并被setTimeoutwhile阻止。

但是,这个代码有一个替代方法可以按预期工作,不会阻止主进程或事件循环:

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) 

在终端:

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

好消息来源:

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

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