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回だけしか実行されないようにガードしてみた。
letisBeforeExitAlreadyFired=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 の頃から変わっていないらしい。あまり使われていないのだろうか…。