[英]How do I stop a Node.js HTTP server programmatically such that the process exits?
我正在編寫一些測試,並希望能夠以編程方式啟動/停止我的 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.')
})
}
測試代碼如下:
// 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 test.js
在my_server.stop()
上退出到 shell,我是否需要解除某些事件的綁定? 如果是這樣,哪個事件和來自哪個對象? 我嘗試通過從中刪除所有事件偵聽器來修改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);
});
});
兩秒后,進程將退出,測試將成功結束。 我還在打開多個客戶端套接字的情況下對此進行了測試; 只要你結束所有客戶端連接,然后在服務器上調用.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'));
}
}
筆記:
要使 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 似乎無事可做,但它繼續運行的事實是其“事件循環”的一個特性,它不斷循環,等待事件發生。
要停止事件循環,請使用 process.exit()。
經過一些小的修改,例如正確使用 module.exports,添加分號等,在 Linux 服務器(Fedora 11 - Leonidas)上運行您的示例按預期運行並盡職盡責地返回到命令外殼。
// 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;
// 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 語法的細節,否則我強烈建議使用顯式分號,而不是依賴 ASI 的隱式分號。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.