Node.jsはサーバサイドJavaScript実行環境です。
このNode.jsの最大な特徴が ノンブロッキングI/O です。
いままでサーバサイドで動く物となるとshellやperl,rubyなどがありましたがノンブロッキングI/Oではありません。
ノンブロッキングI/Oについて
すごーく簡単な例えを言うと ワンオペを効率良くこなす 感じ。
従来のプログラミングでは料理を火にかけてる間完成するまでその場から離れません。
火にかけて、出来上がる間に他の下準備をできる。それがノンブロッキングI/Oです!
あ、具体例がないのでわからない?なるほど。
ファイルを開いて読む/書く、DBに問い合わせるなどの処理が従来であれば結果を返すまで処理を待つのがブロッキングI/Oです。
ノンブロッキングI/Oでは結果を待たずして次の処理へ行きます。
このノンブロッキングI/Oの特徴から処理の順番を制御しようとするとコールバック地獄に陥ったりします。
いま現在、順番制御しようとするとAsyncモジュールを使うのが一般的ですかね。
if...elseをしっかり書こう
やっとこ本題
db.find(sql, function(err, docs){
if(err) return errToNext(err);
docs.forEach(...);
})
例としてこんな書き方をすることがある。
errがあればerrToNext
関数の返り値をリターンする。
errがなければ次のdocs.forEach
を実行する形になる。
だが、ちょっと待ってほしい。
もしもerrToNext
関数内部にブロッキングI/Oを発生させる処理があったら?
return
が返らないで次の処理へ行ってしまい本物のExceptionが発生するので
db.find(sql, function(err, docs){
if(err){
return errToNext(err);
}else{
docs.forEach(...);
}
})
ノンブロッキングI/Oでは面倒臭がらずキチンと書きましょう。
おわりに
今回の件は実際にハマったことを書いてみました。
どんな関数でも呼ぶと順番が保証できない可能性が高いので条件分岐はきっちり書こうという教訓でした。