2012年2月24日

同期処理を非同期に変換-JavaScriptライブラリPot.js+PotLite.jsリリースノート






Pot.js 1.14PotLite.js 1.31 リリースしました。



その前に Pot.js + PotLite.js リファレンス が完成しました (ということにしたい) ので、
お時間あるときにでも覗いてみてください。

結局 /test-for-new-design/ に置いてあるのはファイル消すのも嫌だし
全部リダイレクトさせるようにしました。



Pot.js 1.14 と PotLite.js 1.31 では、Pot.deferreed() ていう関数つくりました。

deferreed は、関数の中の for, for-in, for-of, do, while 等の同期ループを
Pot.Deferred.forEach() などの非同期イテレータに置き換えて関数を再定義します。

前の記事「JavaScript whileループとPot.Deferred.forEverイテレータでCPU使用率を比較」 でも書いてますが、
Pot.js ライブラリのイテレータは CPU の負荷なく実行できます。

ループを置き換えることで、巨大な文字列を扱ったり、ループ回数が未知な処理をする際に
重さについて考えなくて済むようにと、作ってみまみた。

もともとは deferrize() という関数から派生しています。

関数内のコードをトークン単位に分解して、
単純にトークンの数が多いループブロックをメインループとして解析して、
その文に見合った Pot.Deferred イテレータを割り当ててるんですが
ぜんぜん思ったよりたいへんで まだ複雑なものは対応できてないです。
とくに三項演算子 (?:) と function のコンボとか、E4X とかまでは今後の課題。。 にしたいけど、
そこまでしてたらライブラリの方向性違うんじゃないのって思ってしかたないです。

deferreed の 1 コールで zip.deflate 圧縮とかファイル規模への md5 とか非同期化できたら楽そう。

例えば以下のような関数が

// 文字列を 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
});

あと、プラグインみたいなことしたくて Pot.Plugin ての作ったんですが
なにか違うような気がしてならないです。

プラグイン = ただのオブジェクト
になってしまった。

Pot.addPlugin() という関数で任意の関数とかオブジェクトを登録。
Pot.removePlugin() で削除。
Pot.hasPlugin() で確認、Pot.listPlugin() で列挙。

addPlugin した関数は Pot.xxx でアクセスできる。
・・・それって Pot.myFunc = function() {}; でいいじゃん! てなったので、
以下のようにしてみました。
var string = '\t abc\n \t ';

// オリジナルの Pot.trim()
debug(Pot.trim(string)); // 'abc'

// プラグイン関数の登録により Pot.trim() を上書き
Pot.addPlugin('trim', function(s) {
    return s.replace(/^ +| +$/g, ''); // スペース (U+0020) だけ削除するようにする
});

// 登録した Pot.trim()
debug(Pot.trim(string)); // '\t abc\n \t'

// プラグインの trim を削除
Pot.removePlugin('trim');

// 元に戻る
debug(Pot.trim(string)); // 'abc'
元に戻せる (むしろ消えない) ので、
一時的に挙動を変えたい時とか便利かもしれないです。
あと、Pot.globalize() したときに プラグイン関数もグローバル化します。
Pot.globalize() しなくても with (Pot) {...} でもいい気がしてきました。

プラグインの詳細は
Pot.Plugin リファレンス あたりから参照ください。

マニュアルは英語版も含めてちょっとずつ進めています。


以下はレポジトリとかのリンクなど。

Pot.js / PotLite.js

Pot.js は CPU に負荷をかけることなく JavaScript の実行を可能とするユーティリティライブラリです。
PotLite.js は Pot.js の非同期な部分だけを抽出したライトバージョンです。

ダウンロード

マニュアル

その他の情報についてはマニュアル/マニュアルからのリンク から参照ください。



レポジトリ



その他、なにか問題・バグ・感想・指摘などあれば、
コメントやメールまたは @polygon_planet まで送っていただけるとうれしいです。


0 件のコメント:

コメントを投稿