如何以编程方式停止Node.js HTTP服务器,以便进程退出?

我正在写一些testing,并希望能够以编程方式启动/停止我的HTTP服务器。 一旦我停止了HTTP服务器,我希望启动它的进程退出。

我的服务器是这样的:

// file: `lib/my_server.js` var LISTEN_PORT = 3000 function MyServer() { http.Server.call(this, this.handle) } util.inherits(MyServer, http.Server) MyServer.prototype.handle = function(req, res) { // code } MyServer.prototype.start = function() { this.listen(LISTEN_PORT, function() { console.log('Listening for HTTP requests on port %d.', LISTEN_PORT) }) } MyServer.prototype.stop = function() { this.close(function() { console.log('Stopped listening.') }) } 

testing代码如下所示:

 // file: `test.js` var MyServer = require('./lib/my_server') var my_server = new MyServer(); my_server.on('listening', function() { my_server.stop() }) my_server.start() 

现在,当我运行node test.js ,我得到了我期望的stdout输出,

 $ node test.js Listening for HTTP requests on port 3000. Stopped listening. 

但我不知道如何让node test.js产生的进程退出并返回到shell。

现在,我理解(抽象地),只要Node正在监听的事件绑定事件处理程序,Node就一直运行。 为了使node test.jsmy_server.stop()上退出到shell,我需要解除一些事件吗? 如果是这样,哪个事件和从哪个对象? 我已经尝试通过从它删除所有事件侦听器修改MyServer.prototype.stop() ,但没有运气。

要使node.js进程退出,请按照http://nodejs.org/api/process.html#process_process_exit_code中的描述使用process.exit(status)

更新

我一定误解了。

你写道:“…但我不知道如何让节点test.js产生的进程退出并返回到shell。”

process.exit()这样做。

除非使用child_processes模块,否则node.js将在单个进程中运行。 它不会“产生”任何进一步的过程。

事实上node.js继续运行,尽pipe它看起来没有什么可做的事情,它的“事件循环”的一个特性是不断循环,等待事件发生。

要停止事件循环,请使用process.exit()。

UPDATE

经过一些小的修改,比如正确使用module.exports,添加分号等,在Linux服务器上运行你的例子(Fedora 11 – Leonidas)按预期运行,并尽职尽责地返回到命令shell。

LIB / my_server.js

 // file: `lib/my_server.js` var util=require('util'), http=require('http'); var LISTEN_PORT=3000; function MyServer(){ http.Server.call(this, this.handle); } util.inherits(MyServer, http.Server); MyServer.prototype.handle=function(req, res){ // code }; MyServer.prototype.start=function(){ this.listen(LISTEN_PORT, function(){ console.log('Listening for HTTP requests on port %d.', LISTEN_PORT) }); }; MyServer.prototype.stop=function(){ this.close(function(){ console.log('Stopped listening.'); }); }; module.exports=MyServer; 

test.js

 // file: `test.js` var MyServer = require('./lib/my_server'); var my_server = new MyServer(); my_server.on('listening', function() { my_server.stop(); }); my_server.start(); 

产量

 > node test.js Listening for HTTP requests on port 3000. Stopped listening. > 

最后的想法:

我发现,谨慎地使用结尾分号可以帮助我避免各种有害的,难以定位的错误。

虽然大多数(如果不是全部的话)JavaScript解释器提供了一些被称为“自动分号插入”(或者ASI)的东西,而这些东西是基于一套明确定义的规则(参见http://dailyjs.com/2012/04/19/semicolons/很好的描述),有几个例子,这个特性可能无意中违背了程序员的意图。

除非你非常精通JavaScript语法的细节,否则我会强烈build议使用明确的分号而不是依靠ASI的隐式分号。

我几个月来一直在寻找这个问题的答案,我从来没有看到一个不使用process.exit的好答案。 对我来说这很奇怪,这是一个简单的请求,但似乎没有一个好的答案,或者似乎理解停止服务器而不退出进程的用例。

我相信我可能会偶然发现一个解决scheme。 我的声明是我偶然发现了这个; 它并不反映对实际情况的深刻理解。 所以这个解决scheme可能是不完整的,也可能不是唯一的方法,但至less对我来说是可靠的。 为了停止服务器,你需要做两件事:

  1. 在每个打开的连接的客户端调用.end()
  2. 在服务器上调用.close()

下面是一个例子,作为“磁带”testing套件的一部分:

 test('mytest', function (t) { t.plan(1); var server = net.createServer(function(c) { console.log("Got connection"); // Do some server stuff }).listen(function() { // Once the server is listening, connect a client to it var port = server.address().port; var sock = net.connect(port); // Do some client stuff for a while, then finish the test setTimeout(function() { t.pass(); sock.end(); server.close(); }, 2000); }); }); 

两秒钟后,过程将退出,testing将成功结束。 我也testing了这个打开多个客户端套接字; 只要你结束所有的客户端连接,然后在服务器上调用.close() ,你就是好的。

http.Server#closures

https://nodejs.org/api/http.html#http_server_close_callback

 module.exports = { server: http.createServer(app), //Express App maybe ? // Start the server startServer: function() { Configs.reload(); this.server .listen(Configs.PORT) .on('listening', () => console.log('Server is listening on', Configs.PORT)) .on('error', (e) => console.log('Error starting server:', e)); }, // Stop the server stopServer: function() { this.server .close() // Won't accept new connection .on('close', () => console.log('Server stopped')) .on('error', (e) => console.log('Error stopping server:', e)); } } 

注意:只有在所有剩余连接完成处理时才会触发“close”callback
注2:触发process.exit在“closures”callback,如果你想停止这个过程