我有一个创建 web3 websocket 连接的节点 js 进程,如下所示:
web3 = new Web3('ws://localhost:7545')
当进程完成时(我向它发送一个 SIGTERM),它不会退出,而是永远挂起,没有控制台输出。
我在 SIGINT 和 SIGTERM 上注册了一个监听器,以观察进程在 process._getActiveRequests()
和 process._getActiveHandles()
上有哪些处理,我看到了这个:
Socket {
connecting: false,
_hadError: false,
_handle:
TCP {
reading: true,
owner: [Circular],
onread: [Function: onread],
onconnection: null,
writeQueueSize: 0 },
<snip>
_peername: { address: '127.0.0.1', family: 'IPv4', port: 7545 },
<snip>
}
为了完整性,这里是监听信号的代码:
async function stop() {
console.log('Shutting down...')
if (process.env.DEBUG) console.log(process._getActiveHandles())
process.exit(0)
}
process.on('SIGTERM', async () => {
console.log('Received SIGTERM')
await stop()
})
process.on('SIGINT', async () => {
console.log('Received SIGINT')
await stop()
})
看起来 web3 正在打开一个套接字,这是有道理的,因为我从未告诉它关闭连接。通过文档和谷歌搜索,它看起来不像是 web3 对象的关闭或结束方法。
在上面的stop
中手动关闭socket可以让进程成功退出:
web3.currentProvider.connection.close()
谁有更优雅或官方认可的解决方案?我觉得很有趣,你必须手动执行此操作而不是让对象在进程结束时自行销毁。其他客户端似乎会自动执行此操作,而不会明确告诉他们关闭连接。告诉您的节点进程创建的所有客户端无论如何在关闭时关闭它们的句柄/连接可能更清晰,但对我来说,这是出乎意料的。
最佳答案
It feels funny to me that you have to manually do this rather than have the object destroy itself on process end
这感觉很有趣,因为与异步相比,您可能接触过更多的同步编程。考虑下面的代码
fs = require('fs')
data = fs.readFileSync('file.txt', 'utf-8');
console.log("Read data", data)
当你在上面运行时,你会得到输出
$ node sync.js
Read data Hello World
这是一个同步代码。现在考虑相同的异步版本
fs = require('fs')
data = fs.readFile('file.txt', 'utf-8', function(err, data) {
console.log("Got data back from file", data)
});
console.log("Read data", data);
当你运行时你会得到下面的输出
$ node async.js
Read data undefined
Got data back from file Hello World
现在如果你以同步程序员的身份思考,程序应该在最后一个console.log("Read data", data);
处结束,但是你得到的是之后打印的另一条语句。现在觉得好笑吗?让我们在流程中添加一个退出语句
fs = require('fs')
data = fs.readFile('file.txt', 'utf-8', function(err, data) {
console.log("Got data back from file", data)
});
console.log("Read data", data);
process.exit(0)
现在,当您运行该程序时,它会在最后一条语句处结束。
$ node async.js
Read data undefined
但实际上并没有读取文件。为什么?因为你从来没有给 JavaScript 引擎时间来执行挂起的回调。理想情况下,当没有剩余工作要做时(没有挂起的回调、函数调用等...),进程会自动完成。这就是异步世界的工作方式。您应该研究一些不错的 SO 线程和文章
https://medium.freecodecamp.org/walking-inside-nodejs-event-loop-85caeca391a9
https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/
Why doesn't my Node.js process terminate once all listeners have been removed?
How does a node.js process know when to stop?
因此在异步世界中,您需要告诉进程退出,或者当没有未决任务时它会自动退出(您知道如何检查 - process._getActiveRequests()
和 process._getActiveHandles()
)
关于javascript - web3 websocket连接阻止节点进程退出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50632114/