Node.js / express:立即响应客户端请求并在nextTick中继续执行任务

我想将服务器高消耗CPU任务与用户体验分开:

./main.js:

var express = require('express'); var Test = require('./resources/test'); var http = require('http'); var main = express(); main.set('port', process.env.PORT || 3000); main.set('views', __dirname + '/views'); main.use(express.logger('dev')); main.use(express.bodyParser()); main.use(main.router); main.get('/resources/test/async', Test.testAsync); main.configure('development', function() { main.use(express.errorHandler()); }); http.createServer(main).listen(main.get('port'), function(){ console.log('Express server app listening on port ' + main.get('port')); }); 

./resources/test.js:

 function Test() {} module.exports = Test; Test.testAsync = function(req, res) { res.send(200, "Hello world, this should be sent inmediately"); process.nextTick(function() { console.log("Simulating large task"); for (var j = 0; j < 1000000000; j++) { // Simulate large loop } console.log("phhhew!! Finished!"); }); }; 

当请求“本地主机:3000 /资源/testing/asynchronous”我期望浏览器呈现“Hello世界,这应该立即发送”和Node.js继续处理,并在控制台出现“完成”一段时间后一段时间。

相反,浏览器一直等待,直到node.js完成大任务,然后呈现内容。 我试过res.set({ 'Connection': 'close' });res.end(); 但没有按预期工作。 我也没有运气Googlesearch。

应该如何将响应立即发送到客户端,服务器是否继续执行任务? 谢谢。

编辑

在解决scheme中发布fork方法

尝试等待而不是占用CPU:

 res.send("Hello world, this should be sent inmediately"); console.log("Response sent."); setTimeout(function() { console.log("After-response code running!"); }, 3000); 

node.js是单线程的。 如果你用繁忙的循环lockingCPU,整个事情就会停下来,直到完成。

Thakns为Peter Lyons提供帮助,最后主要的问题是firefox buffer:响应不会很长时间来刷新它(所以firefox一直在等待)。

无论如何,对于CPU执行任务,节点会一直挂起直到完成,所以不会出现新的请求。 如果有人需要它,可以通过分叉来实现(使用child_process,参见http://nodejs.org/api/child_process.html中的示例&#xFF09;

不得不说,分叉情况的变化可能需要更长的时间比在不同的蜱中分裂任务。

./resources/test.js:

 var child = require('child_process'); function Test() {} module.exports = Test; Test.testAsync = function(req, res) { res.send(200, "Hello world, this should be sent inmediately"); var childTask = child.fork('child.js'); childTask.send({ hello: 'world' }); }; 

./resources/child.js:

 process.on('message', function(m) { console.log('CHILD got message:', m); }); 

一个好的解决scheme是使用child_process.fork() :它允许你在不同的Node实例中执行另一个JavaScript文件,从而在不同的事件循环中执行 。 当然,你仍然可以通过发送消息在两个进程之间进行通信 :所以,从你的UI进程中 ,你可以发送一个消息给分支进程,让它执行一些东西。

例如,在ui.js

 var ChildProcess = require('child_process'); var heavyTaskWorker = ChildProcess.fork('./heavyTaskWorker.js'); ... var message = { operation: "longOperation1", parameters: { param1: "value1", ... } }; heavyTaskWorker.send(message); 

heavyTaskWorker.js

 process.on('message', function (message) { switch (message.operation) { case 'longOperation1': longOperation1.apply(null, message.parameters); break; ... } }); 

testing在这里,它工作正常!

希望有所帮助!