NodeJs如何创build一个非阻塞计算

我试图让我的头在nodejs中创build一个无阻塞的重计算块。 拿这个例子(剥离其他东西):

http.createServer(function(req, res) { console.log(req.url); sleep(10000); res.end('Hello World'); }).listen(8080, function() { console.log("ready"); }); 

你可以想象,如果我同时打开2个浏览器窗口,第一个将等待10秒钟,另一个将按照预期等待20个。 所以,知道一个callback以某种方式asynchronous的武装,我删除了睡眠,并把这个:

 doHeavyStuff(function() { res.end('Hello World'); }); 

与function简单定义:

 function doHeavyStuff(callback) { sleep(10000); callback(); } 

这当然是行不通的…我也试图定义一个EventEmitter并注册它,但发射器的主要function有发射'完成'之前的睡眠,例如,所以一切都将运行阻止。

我在这里想知道其他人如何编写非阻塞代码…例如,mongojs模块或child_process.exec是非阻塞的,这意味着在代码中的某个地方,它们在另一个线程上分叉进程并听取其事件。 我怎样才能复制这个例如有一个漫长的过程呢?

我完全误解了nodejs范式吗? :/

谢谢!

更新:解决scheme(有点)

感谢对Linus的回答,的确,唯一的办法是产生一个subprocess,比如另一个节点脚本:

 http.createServer(function(req, res) { console.log(req.url); var child = exec('node calculate.js', function (err, strout, strerr) { console.log("fatto"); res.end(strout); }); }).listen(8080, function() { console.log("ready"); }); 

calculate.js可以花时间做它所需要的并返回。 这样,多个请求就可以并行运行。

如果不使用节点中的某些IO模块(如fsnet ),则无法直接执行此操作。 如果你需要做一个长期运行的计算,我build议你在一个subprocess(例如child_process.fork )或者一个队列中这样做。

这是事件循环如何工作的经典误解。

这不是节点唯一的东西 – 如果你在浏览器中有很长时间的计算,它也会被阻塞。 做到这一点的方法是将计算分解成小块,这样可以使事件循环执行 ,从而允许JS环境与其他竞争性调用交错,但是一次只发生一件事。

setImmediate演示可能是setImmediate ,你可以在这里find。

如果你的计算可以分成块,你可以安排执行者每N秒轮询一次数据,然后再运行M秒。 或者专门为那个任务产生一个专门的孩子,这样主线程就不会阻塞。

我们(微软)刚刚发布了可以和Node.js一起工作的napajs ,以便在同一个进程中启用multithreading的JavaScript场景。

你的代码将如下所示:

 var napa = require('napajs'); // One-time setup. // You can change number of workers per your requirement. var zone = napa.zone.create('request-worker-pool', { workers: 4 }); http.createServer(function(req, res) { console.log(req.url); zone.execute((request) => { var result = null; // Do heavy computation to get result from request // ... return result; }, [req]).then((result) => { res.end(result.value); } }).listen(8080, function() { console.log("ready"); }); 

你可以阅读这篇文章的更多细节。