我正在编写一些测试,并希望能够以编程方式启动/停止我的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.')
})
}
Run Code Online (Sandbox Code Playgroud)
测试代码如下:
// 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()
Run Code Online (Sandbox Code Playgroud)
现在,当我跑步时node test.js,我得到了stdout我期望的输出,
$ node test.js
Listening for HTTP requests on port 3000.
Stopped listening.
Run Code Online (Sandbox Code Playgroud)
但我不知道如何让生成的进程node test.js退出并返回shell.
现在,我(抽象地)理解Node只要有正在侦听的事件的绑定事件处理程序就会继续运行.为了node test.js退出shell my_server.stop(),我是否需要取消绑定某些事件?如果是这样,哪个事件和来自哪个对象?我尝试MyServer.prototype.stop()通过删除所有事件监听器来修改,但没有运气.
几个月来我一直在寻找这个问题的答案,而且我还没有看到一个不使用的好答案process.exit.我很奇怪这是一个如此简单的请求,但没有人似乎有一个很好的答案或似乎理解停止服务器而不退出进程的用例.
我相信我可能偶然发现了一个解决方案.我的免责声明是我偶然发现了这个; 它并没有反映出对实际情况的深刻理解.所以这个解决方案可能不完整或者可能不是唯一的方法,但至少它对我来说是可靠的.要停止服务器,您需要做两件事:
.end()在每个打开的连接的客户端调用.close()服务器这是一个例子,作为"磁带"测试套件的一部分:
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);
});
});
Run Code Online (Sandbox Code Playgroud)
两秒钟后,该过程将退出,测试将成功结束.我也用多个客户端套接字测试了这个; 只要你结束所有客户端连接,然后.close()在服务器上调用,你就是好的.
https://nodejs.org/api/http.html#http_server_close_callback
module.exports = {
server: http.createServer(app) // Express App maybe ?
.on('error', (e) => {
console.log('Oops! Something happened', e));
this.stopServer(); // Optionally stop the server gracefully
process.exit(1); // Or violently
}),
// Start the server
startServer: function() {
Configs.reload();
this.server
.listen(Configs.PORT)
.once('listening', () => console.log('Server is listening on', Configs.PORT));
},
// Stop the server
stopServer: function() {
this.server
.close() // Won't accept new connection
.once('close', () => console.log('Server stopped'));
}
}
Run Code Online (Sandbox Code Playgroud)
笔记:
要使 node.js 进程退出,请按照http://nodejs.org/api/process.html#process_process_exit_codeprocess.exit(status)中所述使用
我一定是误会了。
您写道:“...但我不知道如何让节点 test.js 生成的进程退出并返回到 shell。”
process.exit() 就是这样做的。
除非您使用 child_processes 模块,否则 node.js 将在单个进程中运行。它不会“产生”任何进一步的进程。
事实上,即使 Node.js 看起来无事可做,它仍然继续运行,这是其“事件循环”的一个特性,它不断循环,等待事件发生。
要停止事件循环,请使用 process.exit()。
经过一些小的修改(例如正确使用 module.exports、添加分号等)后,在 Linux 服务器(Fedora 11 - Leonidas)上运行示例将按预期运行并忠实地返回到命令 shell。
// 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;
Run Code Online (Sandbox Code Playgroud)
// 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();
Run Code Online (Sandbox Code Playgroud)
> node test.js
Listening for HTTP requests on port 3000.
Stopped listening.
>
Run Code Online (Sandbox Code Playgroud)
我发现,认真使用语句结束分号使我避免了各种有害的、难以定位的错误。
虽然大多数(如果不是全部)JavaScript 解释器都根据一组明确定义的规则提供称为“自动分号插入”(或 ASI)的功能(有关详细信息,请参阅http://dailyjs.com/2012/04/19/semicolons/优秀的描述),在很多情况下,此功能可能会无意中违背程序员的意图。
除非您非常精通 JavaScript 语法的细节,否则我强烈建议您使用显式分号,而不是依赖 ASI 的隐式分号。