javascript 在 Node.js 中,setTimeout() 会阻塞事件循环吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8950978/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
In Node.js, does setTimeout() block the event loop?
提问by TIMEX
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??? Is this true? That's what I heard.
整个服务器在这 10 秒内就死了???这是真的?那是我听到的。
回答by Jamund Ferguson
The answer is no. What your link Node.js: How would you recreate the 'setTimeout' function without it blocking the event loop?showed was not a setTimeout
blocking the event loop it was a while
loop that deliberatelyblocks the event loop. 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.
答案是否定的。你的链接Node.js:你将如何重新创建“setTimeout”函数而不阻塞事件循环?表明不是setTimeout
闭塞事件循环,这是一个while
循环,它故意块事件循环。如果您希望您的服务器速度更快,您不想阻止事件循环。诸如此类的异步回调setTimeout
会很好用。
Are you trying to block for some reason (like testing or something?)
您是否出于某种原因试图阻止(例如测试或其他什么?)
回答by Jerry Tian
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). The interval between the first and second request is 20 seconds, but the second and the third is just 2 seconds.
而且,奇怪的是,它也没有以串行模式运行(如果 Node.js 被 setTimeout 阻止,它应该)。第一个和第二个请求之间的间隔是 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)
回答by JaredPar
That is not true. When you call setTimeout
and return out of your code the server is not blocked. It is free to process other events (possibly other setTimeout
callbacks) while waiting for your particular timer to fire
那不是真的。当您调用setTimeout
并返回代码时,服务器不会被阻止。setTimeout
在等待您的特定计时器触发时可以自由地处理其他事件(可能是其他回调)
回答by Ken Wayne VanderLinde
The link which you seem to be confused about does notstate that setTimeout
will block. Rather, the OP in that question was trying to make a custom function called wait
that would behave like setTimeout
. The wait
function is the blocking function - setTimeout
will not block.
您似乎感到困惑的链接并未说明setTimeout
会阻止。相反,该问题中的 OP 试图创建一个调用的自定义函数wait
,其行为类似于setTimeout
. 该wait
函数是阻塞函数——setTimeout
不会阻塞。
回答by pirs
The main process seems to be monothreaded by host and blocked by a setTimeout
or a while
.
主进程似乎被主机单线程处理并被 asetTimeout
或 a阻塞while
。
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