我发现了几个事件,以确保在应用程序存在之前我的socket.io http服务器已正确关闭:
const app = express()
server = http.createServer(app)
io = sio(server)
process.on('SIGUSR2', shutdownServer)
process.on('SIGINT', shutdownServer)
process.on('uncaughtException', shutdownServer)
function shutdownServer() {
io.close(() => {
server.close(() => process.exit(1))
})
}
现在我挑起了一个致命的错误:
let x = undefined
x.foo()
使用tsc-watch运行脚本,如下所示:
"scripts": {
"clean": "rm -rf dist",
"watch": "npm run clean & tsc-watch -p . --outDir ./dist --onSuccess \"node ./dist/main.js\" --onFailure \"Compile-Error\""
}
我希望在x.foo()
调用之后,我的socket.io服务器关闭,并且Node.js进程存在。但由于未知原因,情况并非如此:在异常之后,我运行ps -aux | grep node | grep main.js
并看到节点进程正在运行。这个节点甚至处理answear socket.io请求!
使用TypeScript的Node.js应用程序,我喜欢在更改时自动重新编译文件。所以我使用了tsc-watch。但是这让我很开心,因为它显示了一些奇怪的行为:首先我在保存更改的文件后随机看EADDRINUSE
。通过在SIGUSR2
信号上杀死服务器和节点,我可以解决这个问题。
后来我学到了很难的方法,这对异常无效。因此,如果我保存中断的代码,旧的Node进程将继续运行。这很难找到,因为在这种情况下,由于未知原因,我没有得到EADDRINUSE
- 尽管旧进程在同一端口上侦听。它显示了旧过程的日志托管。
现在我修复了所有奇怪和不受欢迎的beaviours,除了未捕获的异常问题。我的解决方法是:使用ctrl + c停止观察者,使用ps
在后台获取未停止进程的pid,杀死它们并重新启动观察程序。但那很糟糕。我只是希望tsc-watch
杀死旧的进程/服务器并启动一个新的进程/服务器。根据文档,这就是它的作用:"Notes: Any child process (COMMAND) will be terminated before creating a new one."。
但它不起作用。即使我上面的代码中没有捕获的异常处理程序也无法正常工作,我甚至不知道为什么。互联网包含许多关于uncaughtException
处理程序的帖子,其中有一小部分使用process.exit()
来终止进程。
这是由socket.io/express中的某些setInterval()
函数引起的吗?我也浪费了很多时间,因为当你不打电话unref()
时,这样的电话会一直运行。特别是对于节点终止问题,当节点多次生成并且每次创建这样的无限循环时,这将导致总混乱。但如果这是真的,那么它无法解释为什么我对{。1}}调用socket.io/express不起作用。
所以我正在寻找一种方法来杀死从我的主进程创建的所有进程,子进程和其他东西,这样我在使用close()
开发期间就不会得到任何僵尸。
好的,我发现这只是因为COMPILE错误造成的。上面的示例导致编译错误,因为tsc-watch
没有类型。如果我们这样做:
x
我们收到运行时错误,let x: any = undefined
x.foo()
被称为〜>我的结束工作。但我也想处理编译错误。消息uncaughtException
表示该节点似乎在这里产生子进程,也许这就是我们获得这些行为的原因。
Altough我仍然不明白为什么在这种情况下启动节点?使用spawn Compile-Error ENOENT
编译错误:
src / main.ts(43,4):错误TS2532:对象可能是“未定义”
我认为let x = undefined
在这种情况下得到了一个类型化的常量值,因为它不能与x
不同。 undefined
允许let x: any = undefined
无法输入,这使得另一个值成为可能。
Imho这会导致编译失败,因此不会启动任何节点。这可能是x
的不当行为吗?
认识到我在RPI上的节点客户端问题较少,我看到RPI上的LTS版本(目前是8.11.2),我的开发机器有Arch Linux,因此安装了最新的10.3.0版本。我找到了nvm,一个节点的版本管理器。虽然这似乎是一个好主意,但它会导致我的npm脚本出现问题。我要在我想运行应用程序的每个盒子上安装nvm。
所以我找到了一个更好的解决方案:Node has an official npm-package,可以作为依赖项添加:
tsc-watch
现在您只需使用npm i -P node@v8-lts
来使用本地节点而不是全局安装的节点:
npx node
出于测试目的,我删除了所有信号的上述事件以及通用异常处理程序。我的第一次测试似乎运行良好,没有问题,节点10的情况不是这样。我会密切关注这一点。但似乎[user@antergos server]$ npx node --version
v8.11.1
[user@antergos server]$ node --version
v10.3.0
与节点10不兼容。这有点棘手,因为tsc-watch
没有任何兼容性文档,所以我不知道这个事实。