node.jsで使える非同期コントロールフローライブラリ nue その4

非同期処理前と非同期処理後のコードで値をどう共有するか?
nueでは2つの方法を提供します。

  1. 引数で渡す
  2. flowローカルな変数を介して共有する

グローバル変数とかflowよりも大きなスコープで共有する方法もありますが、ここでは取り上げません。)

1. 引数で渡す。

引数で渡すにはthis.async()に値を設定します。以下の例では最初の関数で使ったパス名を最後の関数でも使いたいので、それぞれの関数でthis.async()に値を設定しています。非同期の処理が絡まない場合はthis.next()で渡すこともできます。

var flow = require('nue').flow;
var fs = require('fs');

flow(
  function () {
    var path1 = 'path1';
    var path2 = 'path2'
    fs.readFile(path1, 'utf-8', this.async(path1));
    fs.readFile(path2, 'utf-8', this.async(path2));
  },
  function (path1, data1, path2, data2) {
    fs.writeFile('path3', data1 + data2, this.async(path1, path2));
  },
  function (path1, path2) {
    fs.readFile('path3', 'utf-8', this.async(path1, path2));
  },
  function (path1, path2, data) {
    if (this.err) throw this.err;
    console.log(data);
    console.log('all done: ' + path1 + ' and ' + path2 + ' are concatenated.');
    this.next();
  }
)();
2. flowローカルな変数を介して共有する。

flowに属する関数はどれもthis.dataというプロパティで同じオブジェクトを参照します。ここに適当な値を追加していけば値が共有できます。flowは複数定義したりネストしたりできますが、this.dataが参照するオブジェクトはflowそれぞれに固有です。それがflowローカルと呼んでいる理由です。

var flow = require('nue').flow;
var fs = require('fs');

flow(
  function () {
    this.data.path1 = 'path1';
    this.data.path2 = 'path2';
    fs.readFile(this.data.path1, 'utf-8', this.async());
    fs.readFile(this.data.path2, 'utf-8', this.async());
  },
  function (data1, data2) {
    fs.writeFile('path3', data1 + data2, this.async());
  },
  function () {
    fs.readFile('path3', 'utf-8', this.async());
  },
  function (data) {
    if (this.err) throw this.err;
    console.log(data);
    console.log('all done: ' + this.data.path1 + ' and ' + this.data.path2 + ' are concatenated.');
    this.next();
  }
)();


flowをネストさせてみます。

var flow = require('nue').flow;

flow(
  function () {
    this.data.x = 'hoge';
    this.next([1]);
  },
  flow(
    function (array) {
      this.data.x = 'foo';
      array.push(2);
      this.next(array);
    }
  ),
  flow(
    function (array) {
      this.data.x = 'bar';
      array.push(3);
      this.next(array);
    }
  ),
  function (array) {
    console.log('this.data.x = ' + this.data.x);
    console.log('array = ' + array);
    this.next();
  }
)();

外側のflowと内側のflowはthis.dataが参照するオブジェクトを共有しません。一方で、引数で渡ってくるオブジェクトは共有できます。という訳で出力結果はこうなります。

this.data.x = hoge
array = 1,2,3