非同期呼び出しの見た目上の同期を実現するためにnode-fibers 使ってみた

laverdet/node-fibers · GitHub https://github.com/laverdet/node-fibers
ネタ元としてはRubyのFiber。

他のcontrol flow系とは経路が違って、V8を直接叩いて実装されている。よって普通のJSの直感から反した挙動を取ることが可能となっているし、nodeでしか動かない。

インストール

いつもの

npm install fibers

使い方

sleepの公式サンプル

var Fiber = require('fibers');
function sleep(ms) {
    var fiber = Fiber.current;
    setTimeout(function() {
        fiber.run();
    }, ms);
    Fiber.yield();
}

Fiber(function() {
    console.log('wait... ' + new Date);
    sleep(1000);
    console.log('ok... ' + new Date);
}).run();
console.log('back in main');

Fiberブロックの中が見た目上同期している。

特徴

他のcontrol flow系ライブラリの when ~ then ~ といったコールバックをキャッチする煩わしさから解放される。かわりに同期的に呼び出したいプロセスをFiberで囲う必要がある。

Fiber.yield が呼ばれると Fiber.current の run が呼ばれるまでは次の処理を止める。

オレオレスニペット

これぐらいラップしてしまうと意識せず使える(気がした)

Fiber = require('fibers')
Block = (main) ->
  sync = (f) ->
    fiber = Fiber.current
    f (-> fiber.run())
    Fiber.yield()
  Fiber(-> main(sync)).run()

Block (sync) ->
  console.log '1'
  sync (done) ->
    setTimeout (-> console.log '2'; done()) , 300
  sync (done) ->
    setTimeout (-> console.log '3'; done()) , 300
  console.log '4'

1,2,3,4と順番に出力される
非同期ならば 1,4, (2 or 3) となるはず