qiita投稿テスト.元エントリ
coのようなモジュール(他にもこことかこことか)がどのような形で実装されているのか知りたいのは僕だけでは無いと思う.理解のために出来る限り単純化してみた.
var co = function(fn){
// callback
var done = function(val){
// yieldに値を流し込む
gen.next(val);
}
// make a generator
var gen = fn(done);
// start
gen.next();
};
// test
// 0~4までをディレイ付きで表示する
co(function*(done){
for(var i=0;i<5;i++){
var val = yield setTimeout(function() { done(i); }, 500);
console.log('val: ', val);
}
});
このコードではco()
のスコープ内で呼ばれたdone(val)
の引数をgen.next(val)
でyieldの返り値として渡している.そのため、done(val)
が呼ばれるまで待つ挙動を実現出来る.
このままでは、done
を常に引数で渡さなくてはいけないし、ジェネレータのネストや並列実行に対応出来ない.これらを実装した最終コードは
co.jsに置いておいた.こちらもco
関数自体は50行ほどで書いてあるので、理解しやすいと思う.
(visionmedia/coとはココロは同じだけれど、実装はかなり違うのでご了承下さい.あくまで勉強用です.特に並列実行は返り値の順番が適当だったりします.)
補足
僕はC++やObj-C出身のエンジニアなので、こういう非同期周りは泥臭いイメージしか無かった.Win8のシンポジウムでC#のasyncについて聞いた時は、激しく興奮した覚えがあったけれど、それがnode.jsのシンプルなジェネレータで簡単に実装できるというのは素晴らしいな、と思う.またこれでnode.jsがひとつ好きになった.
yieldシリーズ、次はchanについて書いてみる.