Node.jsで非同期処理を試してみた。
高木です。こんばんは。
ここのところ、ずっとJavaScriptの話題が続いていますが、今回もそうです。
初心者の私にも言語の仕様が大体分かってきましたので、少しは違ったことに挑戦したいと思います。
今回挑戦するのは非同期処理です。
Node.jsでは非同期処理が重要な要素になっているようなので、外すことはできないでしょう
さて、非同期処理と行ってもとくに目新しいことはありません。
ふだん、組込みや制御関係の仕事が多いので、その手のことは慣れています。
今回は比較的簡単なタイムアウトを試してみることにします。
1 2 3 4 5 | console.log("begin"); setTimeout(() => { console.log("end"); }, 3000); |
まずは上記のようなコードを書いてみました。
スクリプトを実行すると、まず「begin」と出力され、それから3秒ほど経過して「end」と表示されます。
タイムアウトを3秒に設定しているので、期待通りの動作になっています。
普段の私の感覚からすると、仮にタイムアウト時に呼び出されるコールバックを設定しても、そのあと適切にウェイトをかけておかないとプロセスが終了してしまいます。
なので、最初は次のように書いていました。
1 2 3 4 5 6 7 8 9 10 | console.log("begin"); var running = true; setTimeout(() => { console.log("end"); running = false; }, 3000); while (running) { } |
ところがこれだと、いつまで経ってもコールバックが呼び出されません。
それもそのはずで、Node.jsの非同期処理はマルチスレッドでも割り込み処理でもありませんから、永久ループを回してしまうとコールバックに制御が移る機会がありません。
私が普段よく使っている別の環境にはTcl/Tkがあります。
Tcl/Tkでは、CやC++から使うときには、Tk_MainLoop関数を呼び出すかTcl_DoOneEvent関数を繰り返し呼ぶことでコールバックが呼び出されます。
その流儀からの類推もあってのですが、よく考えてみると、Tcl/Tkでもスクリプトだけで書く場合はそのような待ちループは記述しませんね。
じゃあ、タイムアウトを設定したあと、待っている間に他の処理ができないのかというと、そんなことはなさそうです。
以下のようなコードも試してみました。
1 2 3 4 5 6 7 8 9 | function f(n) { console.log(n + ": running..."); setTimeout(() => { console.log(n + ": time out"); }, 1000); } f(1); f(2); |
これだと、ちゃんと次のような結果になります。
1 2 3 4 | 1: running... 2: running... 1: time out 2: time out |
つまり、最初のf関数の呼び出し(f(1))のあと、タイムアウトする前にもう一度f関数の呼び出し(f(2))ができていることを意味しています。
これなら、いい感じに非同期処理ができそうです。