遅延評価を使ってSjaxをAjaxに変換する方法

継続を使ってSjaxをAjaxに簡単に変換する方法
http://d.hatena.ne.jp/llamerada/20070220/1171984586

を見て。こんなのはどうだろう。

ユーザーからの入力や、非同期のHTTPリクエストなんかを、具体化されてないオブジェクトとして捉えて、それらを受け取った関数側が遅延オブジェクトを具体化するためのリクエストを投げて再試行する。ネストが深くならないですむ、同期処理で書く場合との変更点が少ない、あるいは完全に差異を無くすことができる。

alert(args)のコメントを外せば、引数が具体化されていく様子が分かるはず。

Function.prototype.receive_lazy = function(){
    var orig = this;
    return function(){
        var thisObj = this;
        var me = arguments.callee;
        var args = Array.prototype.slice.apply(arguments);
        // alert(args);
        function retry(i, as_force){
            return function(arg){
                if(!isLazy(args[i])) args[i] = args[i].value;
                if(as_force && typeof arg == "function"){
                    arg(me.apply(thisObj, args));
                } else {
                    return me.apply(thisObj, args)
                }
            }
        }
        for(var i=0;i<args.length;i++){
            if(isLazy(args[i])){
                args[i].force(retry(i));
                return {isLazy:true, force: retry(i, true)}
            }
        }
        return orig.apply(this, args);
    }
};
function isLazy(obj){
    return typeof obj == "object" && obj.isLazy
}

// ここからが実際に記述する部分
function fetch(path, length, offset, cont){
    var range = ["bytes=" + offset + "-" + (offset + length - 1)].join("");
    var options = {
        method: "get",
        onComplete: function(request){cont(request.responseText);},
        requestHeaders: ["Range", range]
    }
    new Ajax.Request(path, options);
}
fetch = fetch.receive_lazy();
function lazy_fetch(path, length, offset, inflate){
    var lazy_object = {
        isLazy: true,
        force: function(callback){
            fetch(path, length, offset, function(responseText){
                lazy_object.isLazy = false;
                lazy_object.value = 
                    (typeof inflate == "function")
                     ? inflate(responseText) 
                     : responseText;
                callback(lazy_object.value);
            });
        }
    };
    return lazy_object;
};
function fetch_data(){
    var path = "/data.txt";
    var offset = lazy_fetch(path, 4, 0, parseInt);
    var length = lazy_fetch(path, 4, 4, parseInt);
    return lazy_fetch(path, length, offset);
}

// ここでalertも変形させてしまえば同期処理のコードとほとんど同じになる
fetch_data().force(alert)


処理の流れは、
- lazyなオブジェクトを引数に受け取ったら
-- 引数を具体化するためのforceメソッドを呼び出す
-- オブジェクトが具体化されたら、関数を再度実行する
- 全ての引数が具体化されたらオリジナルの関数に処理を引き渡す

Function.prototypeにreceive_lazyメソッドを加えて、あらかじめ遅延評価な変数を受け取れるように関数を変形しておく必要がある。考え方としては、コードを書くときに非同期処理を完全に意識しないで済むようにしたい。非同期に合わせて書くのではなく、同期処理のつもりで書いたコードが、いつのまにやら非同期処理になってる、というのがやりたい。


WriteBacks

Posted by at 2007/02/23 (Fri) 09:27:45

アデランス

アデランス

Posted by アデランス at 2007/02/23 (Fri) 09:28:26

Posted by at 2007/02/25 (Sun) 08:12:55

アートネーチャー

アートネーチャー

Posted by アートネーチャー at 2007/02/25 (Sun) 08:13:46

Future

Futureパターンってやつですね
Java には標準で入ってるので参考になるかも。

Posted by dai at 2007/03/02 (Fri) 11:08:12

Posted by at 2007/04/17 (Tue) 17:09:16

cheap phentermine

Combien il co短te, pour d辿velopper un drapeau sur ton blog?

Posted by buy phentermine at 2007/09/14 (Fri) 06:37:52

Posted by at 2007/12/05 (Wed) 00:37:24

Posted by 月極駐車場 at 2008/10/21 (Tue) 14:35:27

Link/Javascript/Ajax

Link/Javascript/Ajax ▲&nbsp;▼Contents Link/Javascript/Ajax Contents Ajax概要 Ajaxを学ぶ Ajaxを使う Ajax開発 開発 リファレンス 文字化け XMLHttpRequest クロスドメイン 開発ツール デザイン サンプルアプリ Ajaxと連携 Aj...

Posted by [ abs+ ] (PukiWiki/TrackBack 0.3) at 2009/03/20 (Fri) 01:28:20
TrackBack ping me at
http://la.ma.la/blog/diary_200702210356.trackback
Post a comment

writeback message: Ready to post a comment.







spam yoke. nanimo ireruna.