我有一个普通的nodejs服务器,如下所示:
let someVar // to be set to a Promise
const getData = url => {
return new Promise((resolve, reject) => {
https.get(
url,
{ headers: { ...COMMON_REQUEST_HEADERS, 'X-Request-Time': '' + Date.now() } },
res => {
if (res.statusCode === 401) return reject(new RequestError(INVALID_KEY, res))
if (res.statusCode !== 200) return reject(new RequestError(BAD_REQUEST, res))
let json = ''
res.on('data', chunk => json += chunk)
res.on('end', () => {
try {
resolve(JSON.parse(json).data)
} catch (error) {
return reject(new RequestError(INVALID_RESPONSE, res, json))
}
})
}
).on('error', error => reject(new RequestError(FAILED, error)))
})
}
const aCallback = () =>
console.log('making api call')
someVar = getData('someApiEndpoint')
.then(data => { ... })
}
const main = () => {
const server = http.createServer(handleRequest)
anInterval = setInterval(aCallback, SOME_LENGTH_OF_TIME)
const exit = () => {
server.close(() => process.exit())
log('Server is closed')
}
process.on('SIGINT', exit)
process.on('SIGTERM', exit)
process.on('uncaughtException', (err, origin) => {
log(`Process caught unhandled exception ${err} ${origin}`, 'ERROR')
})
}
main()
我遇到了这样一种情况:我将执行ctrl-c
,并将看到Server is closed
日志,然后是命令提示符,* 但随后我将看到更多的日志打印出来,表明正在进行更多的API调用 。
在exit()
内调用clearInterval(anInterval)
(在server.close()
之前)似乎解决了即使服务器关闭时间隔仍继续的问题,所以这很好。但是:
从这些节点文档:
关闭连接到此服务器的所有连接*,这些连接没有发送请求或等待响应**。
也就是说,我假设server.close()
不会自动终止http请求。
当我的计算机/节点不再跟踪变量someVar
时,http响应信息会发生什么变化?
如果不专门终止发出http请求(并等待响应)的线程,会有什么后果?
是否有取消请求的最佳实践?
这包括什么(即,我最终会告诉API的服务器“没关系,请不要发送任何东西”,还是我只是指示节点不要接收任何新信息)?
1条答案
按热度按时间zkure5ic1#
有几件事你应该知道。首先,在软件中处理SIGINT是一件复杂的事情。其次,你永远不需要调用
process.exit()
,因为节点总是在它准备好的时候退出。如果你的进程没有正确退出,那意味着有“工作正在完成”,你需要停止。一旦没有更多的工作要做,节点将安全地自行退出。通过示例可以很好地解释这一点。让我们从这个简单的程序开始:如果运行这个程序,然后按Ctrl + C(发送SIGINT信号),节点会自动清除间隔并退出(嗯......这更像是“致命”退出,但这超出了这个答案的范围)。
现在,如果你运行这个程序并按下Ctrl + C,你会看到 “SIGINT received” 消息,但进程永远不会退出。当你听到SIGINT时,你是在告诉节点“嘿,我有一些事情需要在你退出之前清理”。节点会等待任何“正在进行的工作”完成后才退出。如果节点最终没有自己退出,它会告诉你“嘿,我可以看到有一些东西仍在运行-你需要停止他们之前,我将退出”。
让我们看看清除间隔后会发生什么:
现在,如果你运行这个程序并按下Ctrl + C,你会看到 “SIGINT received” 消息,进程将顺利退出。一旦我们清除了间隔,节点就足够聪明地看到没有发生任何事情,它将退出。这里重要的一课是,如果你监听
SIGINT
,你将等待任何任务完成。您应该永远不需要调用process.exit()
。至于这与您的代码有何关系,您需要做三件事:
当程序退出时,您需要清理上述各项。在最简单的情况下,您应该执行以下操作:
server.close();
clearInterval(anInterval);
request.destroy()
您可能决定在关闭服务器之前等待任何传入的请求完成,或者您可能希望侦听传出请求的“close”事件以检测任何丢失的连接。这取决于您。您应该阅读node
http
docs中可用的方法和事件。希望现在您已经开始了解SIGINT在软件中是如何复杂的。祝您好运。