web-dev-qa-db-ja.com

終了時に非同期操作を実行する方法

プロセスが終了する前に非同期操作を実行しようとしています。

「終了」とは、終了の可能性をすべて意味します。

  • _ctrl+c_
  • 捕捉されなかった例外
  • クラッシュ
  • コードの終わり
  • なんでも.

私の知る限りでは、exitイベントは同期操作のためにそれを行います。

Nodejsのドキュメントを読んで、 beforeExit イベントが非同期操作用であることがわかりましたBUT:

「beforeExit」イベントは、process.exit()の呼び出しやキャッチされない例外など、明示的な終了を引き起こす条件に対しては発行されません。

「beforeExit」は、追加の作業をスケジュールする意図がない限り、「exit」イベントの代わりとして使用しないでください。

助言がありますか?

22
Kesem David

終了する前に、シグナルをトラップして非同期タスクを実行できます。このようなものは、終了する前にterminator()関数を呼び出します(コード内のjavascriptエラーも)。

process.on('exit', function () {
    // Do some cleanup such as close db
    if (db) {
        db.close();
    }
});

// catching signals and do something before exit
['SIGHUP', 'SIGINT', 'SIGQUIT', 'SIGILL', 'SIGTRAP', 'SIGABRT',
    'SIGBUS', 'SIGFPE', 'SIGUSR1', 'SIGSEGV', 'SIGUSR2', 'SIGTERM'
].forEach(function (sig) {
    process.on(sig, function () {
        terminator(sig);
        console.log('signal: ' + sig);
    });
});

function terminator(sig) {
    if (typeof sig === "string") {
        // call your async task here and then call process.exit() after async task is done
        myAsyncTaskBeforeExit(function() {
            console.log('Received %s - terminating server app ...', sig);
            process.exit(1);
        });
    }
    console.log('Node server stopped.');
}

コメントでリクエストされた詳細を追加:

  • ノードの ドキュメント から説明される信号、このリンクは標準 POSIX信号名 を参照
  • 信号は文字列でなければなりません。ただし、他の人がチェックを行ったので、知らない予期しないシグナルが他にある可能性があります。 process.exit()を呼び出す前に確認したいだけです。とにかくチェックに時間がかからないと思います。
  • db.close()の場合、使用しているドライバーに依存すると思います。それが非同期の同期かどうか。非同期であり、dbを閉じた後に何もする必要がない場合でも、async db.close()が単にcloseイベントを発行し、サーバーが終了したかどうかに関係なくイベントループが処理を続けるため、問題ありません。
13
Ben

BeforeExitフックの使用

「beforeExit」イベントは、Node.jsがイベントループを空にして、スケジュールする追加の作業がない場合に発生します。通常、スケジュールされた作業がない場合、Node.jsプロセスは終了しますが、「beforeExit」イベントに登録されたリスナーは非同期呼び出しを行うことができるため、Node.jsプロセスが続行されます。

process.on('beforeExit', async () => {
    await something()
    process.exit(0) // if you don't close yourself this will run forever
});
1
Sceat