node-fiberでライフチェンジングとか煽ったことを若干後悔してる
承前→ node.jsのvmとsynchronizeはライフチェンジング - taiyoh's memorandum
@hokaccha先生の記事読んで、やっぱインフルエンサーが書くと内容の充実度も反応も全然違うなー、とか思ってたのですが、特にあの記事をぶくましてるけどfiber使ったことない人は、使いどころをちゃんと見極めた方がいい、という注意喚起。もしくは過去の自分の記事に対する懺悔。
実は以前qiitaにこっそり投稿してたんだけど、以下の処理の時にエラーが発生する。
// sync_test.js var sync = require('synchronize'); sync.fiber(function() { try { sync.await((function(defer) { console.log("await 1 start"); setTimeout(function() { console.log("await 1 end"); try { sync.await((function(defer2) { console.log("await 2 start"); setTimeout(function() { console.log("await 2 end"); defer2(null, 'ok'); }, 1000); })(sync.defer())); console.log("await 2 over"); defer(null, "ok"); } catch(e) { console.log("await 2 error", e); defer(e, null); } }, 1000); })(sync.defer())); } catch(e) { console.log("await 1 error", e); } console.log("await 1 over"); });
ずらずら長いが、端的に言えば、sync.await中にもう一回sync.awaitしたらどうなるか、ということを検証したもの。結果は以下のとおりになる。
% node sync_test.js await 1 start await 1 end await 2 error [Error: no current Fiber, defer can'b be used without Fiber!] await 1 error [Error: no current Fiber, defer can'b be used without Fiber!] await 1 over
これだけだとピンとこないかもしれない。じゃあ以下のパターンがあった時は?
- ちょっと大きめのDBのselect文をsync.awaitで発行してる最中に、別のリクエストでsync.awaitを使ってファイルへの書き込みをする
- OAuth認証の処理をsync.awaitで発行してる最中に別のリクエストでsync.awaitを使ったselect文を発行する
他にも色々あると思うけど、ふつーにこういうウェブアプリケーション書いてしまうと、確実にエラーが発生し、「テストでは通ってるけど、本番に上げたらなんかちょくちょくエラーが起きる」という事態が発生する。シングルスレッドでこなすnodeならではの現象だと思う。PerlとかRubyみたいにpreforkしてリクエストを処理したらどうなるかはわからない(そもそもできるのか?このへんは自分はよく知らない)。でも、そういうアプリケーションを書く人は、よっぽどの変態か「自分はJS以外の言語を知らないから」という消極的な理由でアプリケーション実装を選択してるか以外にないだろうと思う。
要は、プロセス中のシーケンスが単一であればいい。なので、バッチスクリプトを書くときなんかは、すごく効果的なんじゃないかと思う。バッチ実装で非同期とか考えないでいい筈なのにコールバック地獄とか、ただの面倒事でしかないので。