在server.close()之后放弃http请求?



我有一个香草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的服务器'没关系,请不要发送任何东西',或者我只是指示节点不要接收任何新信息)?

您应该注意几件事。首先,在软件中处理SIGINT是一件复杂的事情。接下来,您永远不需要调用process.exit(),因为节点在准备好后总是会退出。如果您的进程没有正确退出,这意味着有"工作正在完成"。你需要停下来。一旦没有更多的工作要做,节点将自行安全退出。举例说明这一点最好。让我们从这个简单的程序开始:

const interval = setInterval(() => console.log('Hello'), 5000);

如果你运行这个程序,然后按下Ctrl + C(它发送SIGINT信号),node会自动为你清除间隔并退出(嗯…它更像是"致命的"。退出,但这超出了这个答案的范围)。一旦监听SIGINT事件,这种自动退出行为就会改变:

const interval = setInterval(() => console.log('Hello'), 5000);
process.on('SIGINT', () => {
console.log('SIGINT received');
});

现在如果你运行这个程序并按下Ctrl + C,你会看到&;SIGINT received&;消息,但是进程永远不会退出。当你监听SIGINT信号时,你是在告诉节点"嘿,我有一些东西需要在你退出之前清理"。节点将等待任何"正在进行的工作"。在它退出之前完成。如果node最终没有自己退出,它会告诉你"嘿,我看到还有一些东西在运行——你需要在我退出之前阻止它们"。

让我们看看如果我们清除间隔会发生什么:

const interval = setInterval(() => console.log('Hello'), 5000);
process.on('SIGINT', () => {
console.log('SIGINT received');
clearInterval(interval);
});

现在,如果您运行这个程序并按Ctrl + C,您将看到&;SIGINT received&;消息,并且进程将顺利退出。一旦我们清除了间隔,node就足够聪明,可以看到没有发生任何事情,并退出。这里的重要教训是,如果您侦听SIGINT,那么等待任何任务完成的责任就在您身上,您应该永远不需要调用process.exit()

至于这与你的代码的关系,你有三件事要做:

  • http服务器监听请求
  • 间隔
  • 即将离任的https。get请求

当你的程序退出时,清理上面的项目是你的责任。在最简单的情况下,您应该执行以下操作:

  • 关闭服务器:server.close();
  • 清除时间间隔:clearInterval(anInterval);
  • 销毁所有传出请求:request.destroy()

您可以决定在关闭服务器之前等待任何传入请求完成,或者您可能想要侦听传出请求的'close'事件以检测任何丢失的连接。那是你的责任。您应该阅读节点http文档中提供的方法和事件。希望到目前为止,您已经开始了解SIGINT在软件中是一个多么复杂的问题。好运。

最新更新