Node.js で終了時のクリーンアップ処理を書こうとすると、 exit
イベントか beforeExit
イベントの2択になる。 exit
だと非同期処理が書けないので、事実上 beforeExit
の1択…と思って使ってみたらちょっとだけハマったのでメモ。
process.on('beforeExit', (code) => {
console.log('Delayed');
setTimeout(() => {
console.log('Process beforeExit event with code: ', code);
}, 1000);
});
process.on('exit', (code) => {
console.log('Process exit event with code: ', code);
});
console.log('This message is displayed first.');
こんな感じの検証コードを書いて実行したら、 beforeExit
の部分がこんな感じで延々実行されて止まらなくなった。
This message is displayed first.
Delayed
(1秒ウェイト)
Process beforeExit event with code: 0
Delayed
(1秒ウェイト)
Process beforeExit event with code: 0
Delayed
(1秒ウェイト)
Process beforeExit event with code: 0
Delayed
(1秒ウェイト)
...
どうも beforeExit
の中で非同期処理を書くと、そこで「イベントループが空ではなくなった」ということで beforeExit
発火前の状態に戻ってしまうらしい。ぐぬぬ。
仕方ないので、1回だけしか実行されないようにガードしてみた。
let isBeforeExitAlreadyFired = false;
process.on('beforeExit', (code) => {
// beforeExit を1回しか実行させないためのガード条件
if (isBeforeExitAlreadyFired) {
return;
}
isBeforeExitAlreadyFired = true;
console.log('Delayed');
setTimeout(() => {
console.log('Process beforeExit event with code: ', code);
}, 1000);
});
process.on('exit', (code) => {
console.log('Process exit event with code: ', code);
});
console.log('This message is displayed first.');
This message is displayed first.
Delayed
Process beforeExit event with code: 0
Process exit event with code: 0
めでたしめでたし。
参考
- Node.js Documentation
-
Process on beforeExit doesn't work correctly?
ここを見る限り、このbeforeExit
の振る舞いは v0.x の頃から変わっていないらしい。あまり使われていないのだろうか…。