Pot.Deferred.deferreed

{Function} Pot.Deferred.deferreed ({Object|Function} object [, {String|Function} method])

Pot.js と PotLite.js で利用可能。

関数内の同期ループ処理を非同期イテレータに置き換え Deferred 化して返します。

与えられた関数の中で実行される同期ループ (for, for-in, for-of, do, while 等) を
非同期イテレーション (例えば Pot.Deferred.forEach() など) に変換し、再定義した関数を返します。
生成した関数は、Pot.Deferred インスタンスを返します。
deferreed は、一見 deferrize() と似ていますが動作は異なります。
引数 object は、変換する関数の親オブジェクトを指定します。
引数 method は、変換する対象の関数名を文字列で指定します。
object に関数オブジェクトを渡した場合、method は省略できます。
戻り値は 関数オブジェクトになり、Pot.Deferred.forEach() などと同じく 速度の指定が可能です。

var deferfunc = Pot.deferreed(func);
deferfunc(); // 通常の速度で実行
deferfunc.slow(); // 遅めで実行

上の例のように func.slow() のようにして速度の指定ができます。
指定できる名前は以下の表を参照ください。
デフォルトの速度は normal です。

値 / メソッド名 速度
limp 最も遅い
doze 遅い
slow 遅め
normal 通常
fast 速め
rapid 速い
ninja 最も速い

deferreed は、確実に for 文などを変換できるわけではありません。
想定内の複雑でないコードが対象です。
変換に失敗などエラーが起きると、その error インスタンスを throw します。

Pot.globalize() が適応されている場合、Pot.deferreed() が deferreed() で実行できます。

非同期イテレータに置き換えられた関数オブジェクトが返ります。
失敗すると、error インスタンスを throw します。

// 文字列を charCode からなる配列にして返す関数
var toCharCode = function(string) {
    var result = [];
    for (var i = 0; i < string.length; i++) {
        result.push(string.charCodeAt(i));
    }
    return result;
};

// deferreed により for 文を非同期イテレータにした関数を生成
var toCharCodeDefer = Pot.deferreed(toCharCode);

// 例えば toCharCodeDefer は内部で以下のように変換されます
//
//  function(string) {
//      var result = [];
//      return Pot.Deferred.repeat(string.length, function(i) {
//          result.push(string.charCodeAt(i));
//      }).then(function() {
//          return result;
//      });
//  };
//

// Pot.Deferred インスタンスが返るため then() などで繋げられる
toCharCodeDefer('abc').then(function(res) {
    Pot.debug(res); // [97, 98, 99]
});

// この変化により、巨大な文字列でも負荷を分散させ実行できる
var largeString = new Array(100000).join('abcdef');

// 'slow' などの指定が可能
toCharCodeDefer.slow(largeString).then(function(res) {
    Pot.debug(res.length); // 599994
});
// 文字列を圧縮/解凍するオブジェクト (LZ77)
// http://polygon-planet.blogspot.com/2011/02/lz77javascript.html
var TinyLz77 = {
  // 同期処理で圧縮
  compress : function(s) {
    var a = 53300, b, c, d, e, f, g = -1,
        h, i, r = [], x = String.fromCharCode;
    if (!s) {
      return '';
    }
    s = new Array(a--).join(' ') + s;
    while ((b = s.substr(a, 256))) {
      for (c = 2, i = b.length; c <= i; ++c) {
        d = s.substring(
            a - 52275,
            a + c - 1
        ).lastIndexOf(b.substring(0, c));
        if (!~d) {
          break;
        }
        e = d;
      }
      if (c === 2 || c === 3 && f === g) {
        f = g;
        h = s.charCodeAt(a++);
        r.push(
            x(h >> 8 & 255),
            x(h & 255)
        );
      } else {
        r.push(
            x((e >> 8 & 255) | 65280),
            x(e & 255),
            x(c - 3)
        );
        a += c - 1;
      }
    }
    return r.join('');
  },
  // 同期処理で解凍
  decompress : function(s) {
    var a = 53300, b = 0, c, d, e, f, g,
        h, r = new Array(a--).join(' '),
        x = String.fromCharCode;
    if (s && s.length) {
      do {
        c = s.charCodeAt(b++);
        if (c <= 255) {
          r += x((c << 8) | s.charCodeAt(b++));
        } else {
          e = ((c & 255) << 8) | s.charCodeAt(b++);
          f = e + s.charCodeAt(b++) + 2;
          h = r.slice(-52275);
          g = h.substring(e, f);
          if (g) {
            while (h.length < f) {
              h += g;
            }
            r += h.substring(e, f);
          }
        }
      } while (b < s.length);
    }
    return r.slice(a);
  }
};
// これを非同期ループに変換
var compressDefer   = Pot.deferreed(TinyLz77, 'compress');
var decompressDefer = Pot.deferreed(TinyLz77, 'decompress');

var string = 'foooooooooo baaaaaaaaaaaaar baaaaaaazzzzzzzzzzzz';

Pot.debug(string.length); // 48

// 圧縮
compressDefer(string).then(function(compressedString) {
  Pot.debug(compressedString.length); // 26

  // 解凍
  return decompressDefer(compressedString).then(function(decompressedString) {
    Pot.debug(decompressedString.length); // 48
  });
});