明确解决“阻止代码”?

我正在从Node Beginner Book和随后的电子书购买中学习node.js。 在这本书中,Manuel Kiessling解释说,像这样的一行代码:

fs.readFileSync(blah); 

将阻止整个节点进程和所有请求进来。这对于多用户网站来说真是糟糕了!

这就是基斯林使用的例子:

 exec("ls -lah", function( error, stdout, stderr ) { response.writeHead(200, {"Content-Type": "text/plain"}); response.write(stdout); response.end(); }); 

这是欺骗我的代码。 他说ls -lah很容易被find / -name "*"或者数据库查找等更耗时的操作所取代。 我认为昂贵的阻塞操作会以某种方式明确地在后台运行,因为asynchronouscallback。

所以我必须用这个代码来testing我的理论:

 var http = require("http"); var url = require("url"); badSleep = function(ms) { var now = new Date(); var finishAtDate = now.getTime() + ms; console.log("CPU burning sleep for " + ms + " milliseconds"); while(new Date() < finishAtDate) { // do nothing } }; asyncWrapper = function(callback) { //badSleep(3000); callback(); } http.createServer(function(request, response) { var pathname = url.parse(request.url).pathname; console.log("Serve up " + pathname); if (pathname == '/favicon.ico') { response.writeHead(404); response.end(); } else { asyncWrapper(function() { badSleep(3000); response.writeHead(200, {"Content-Type": "text/plain"}); response.write("\nI was wrong " + new Date()); response.end(); }); } }).listen(8888); 

问题是,无论我在哪里睡觉,它仍然阻塞节点事件循环。 callback不能解决阻塞问题。 SO的好用户也在评论中告诉我这一点。

那么exec如何做呢? 我很困惑,所以我去看了github上的subprocess代码 。 我发现exec调用spawn ! 它使一个孩子的过程! 谜团已揭开。 asynchronous代码不能“解决”阻塞问题,产卵。

这导致我的问题。 expression方式不知何故解决阻塞问题,还是你还要担心呢?

PS:这个问题是一个重大的重写。 我想请求下面的SO用户的赦免,并感谢他们对我的耐心。 我在这里肯定学到了一些东西。

有人发表了关于理解节点js事件循环的评论。 对,就是这样。 如果将其封装在asynchronous调用中,则可以发出阻塞调用,因为您没有阻止节点事件循环。

如果你用asynchronous调用包装同步调用,你仍然会遇到阻塞。 例如,如果你写这样的东西:

 fs.readFile("file1.txt", function(err, data1) { var data2 = fs.readFileSync("file2.txt"); }); 

这个进程在读取file1.txt时不会被阻塞,因为你正在使用一个asynchronous调用,但是一旦它读完file1并且到达它读取file2的那一行, 它就会被阻塞

通过在asynchronous/非阻塞调用中发出同步/阻塞调用,您只会延迟阻塞。

你是正确的阻止整个网站是非常糟糕的,这就是为什么你不应该非常频繁地发出阻塞呼叫。 由于node.js是从头开始编写的,因此大多数I / O调用默认是asynchronous的,您应该尽可能使用这些而不是同步调用。

问题是,expression是否自动为你处理,还是你还要担心呢?

你还是要担心。

问题是,expression是否自动为你处理,还是你还要担心呢?

你还是要担心。 NodeJS是单线程的,这意味着每一个同步操作都会完全阻塞它,不pipe它在哪里被调用。 Express或任何其他框架都不能在不阻止服务器的情况下使用同步操作。 简单

 var x = 1; 

已经阻塞了整个服务器,直到完成创build新variables并为其分配新的值。

asynchronous体系结构的重点在于它比线程更高效。 不要被愚弄,因为没有隔离,asynchronous编程就更困难。 如果一个线程失败其他工作,而在asynchronous服务器一个例外可以打破整个服务器。

问题是你可以阻止主节点事件循环!

这句话表明,NodeJS比主事件循环更重要。 这不是真的。 每个代码都在主循环中调用。

也看看这个:

事件循环与multithreading阻塞IO

任何对非asynchronous函数的调用都会“阻塞”,即使它被另一个函数包装了。 唯一的例外是如果包装函数可以推迟到另一个线程/进程的处理(例如,像cluster API)。