yieldを使って非同期->同期(続き)

元ネタ:
http://labs.cybozu.co.jp/blog/kazuho/archives/2007/05/coopthread.php

これを見て書いたエントリ:
http://d.hatena.ne.jp/shinichitomita/20070525/1180106472

上のエントリは、実装前とはいえかなり大間違いなスクリプト書いてる。何やってるんだか。
とりあえず先のエントリのコメントで「for ループの中でyield使えばできる」とわざわざもらったので、ちょっとやってみる。

/**
 * del.icio.usのJSONP呼び出し。非同期でコールバック関数に値が呼び戻される。
 */
function getDeliciousNetwork(id, callback) {
  var url = 'http://del.icio.us/feeds/json/network/'+id;
  jsonp.invoke(url, callback);
}

function getDeliciousPosts(id, callback) {
  var url = 'http://del.icio.us/feeds/json/'+id;
  jsonp.invoke(url, callback);
}

/**
 * 非同期コールバックを引数の最後にとる関数を同期化する。
 */
Function.prototype.synchronize = function(next) {
  var _orig = this;
  return function() {
    var args = Array.prototype.slice.apply(arguments);
    var obj = {};
    _orig.apply(this, args.concat(function(data) {
      obj.value = data; 
      next();
    }));
    return obj; 
  }
}

で、元ネタのrunnable関数はそのままで、こんな感じで実装。

runnable(function(next) {
  var getDeliciousNetworkSync = getDeliciousNetwork.synchronize(next);
  var getDeliciousPostsSync = getDeliciousPosts.synchronize(next);
  var network = getDeliciousNetworkSync('stomita');
  yield;
  network = network.value;
  for (var i=0; i<network.length; i++) {
    var posts = getDeliciousPostsSync(network[i]);
    yield;
    print(posts.value);
  }
})

終わったあとにStopIterationなんちゃらのExceptionが出るけどまあ無視。

上記のrunnableみたいなやつでプロセスを外側から囲わなければ駄目な点と、yieldの後にわざわざ値を取り出す作業が必要というところ(これは巧くできないかな?)、そしてやっぱりyieldが表に出てしまうのが微妙に美しくない気がするのは、多くを求め過ぎ?