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 }); });