每周優(yōu)秀代碼賞析—Jscex內(nèi)核【一】
2011-11-24 08:49 【當耐特】 閱讀(5240) 評論(14) 收藏 舉報一.簡介
Jscex is JavaScript implementation of F#'s Computation Expressions.

它的靈感的源于F#,它為JavaScript語言提供了一個monadic擴展。Jscex完全使用JavaScript編寫,能夠在任意支 持ECMAScript 3的引擎里使用(例如各瀏覽器或Node.js)。Jscex的JIT編譯器能在運行時將JavaScript代碼編譯成Monad形式,無需額外編譯步 驟,并內(nèi)置異步編程類庫,可以大大簡化JavaScript下的異步編程體驗。
二.原理探析
先揭開Jscex 內(nèi)核之前我們先體驗一下世界上最簡單的一個 Jscex例子:
var i = 0;
var countAsync = eval(Jscex.compile("async", function () {
while (true) {
i++;
document.getElementById("show").innerHTML = i;
$await(Jscex.Async.sleep(1000));
}
}))
countAsync().start();
一個計數(shù)器,從0開始每秒鐘加1并顯示出來。
然后我們把countAsync alert出來,看看Jscex把它compile成什么個樣子:
function () {
var $$_builder_$$_0 = Jscex.builders["async"];
return $$_builder_$$_0.Start(this,
$$_builder_$$_0.Loop(
function () {
return true;
},
null,
$$_builder_$$_0.Delay(function () {
i++;
(document.getElementById("show")).innerHTML = i;
return $$_builder_$$_0.Bind(Jscex.Async.sleep(1000), function () {
return $$_builder_$$_0.Normal();
});
}),
false
)
);
}
一個匿名函數(shù),然后用eval().start()執(zhí)行該匿名函數(shù)。
那么上面還能拆開嗎?如果作為一個純粹的.NET或者JAVA程序員,看這段代碼肯定很費勁,因為funciton里套funciton,return套return.
如果你知道javascript的執(zhí)行順序的話,上面的函數(shù)是還可以拆的:
var count = 0;
function doCount() {
count++;
document.getElementById("clock").innerHTML = count;
}
var $$_builder_$$_0 = Jscex.builders["async"];
var delayCount = $$_builder_$$_0.Delay(function () {
doCount();
return $$_builder_$$_0.Bind(Jscex.Async.sleep("1000"), function () {
return $$_builder_$$_0.Normal();
});
});
var loopCount = $$_builder_$$_0.Loop(
function () {
return true;
},
null,
delayCount,
false
);
var countAsync = $$_builder_$$_0.Start(this, loopCount);
countAsync.start();
這樣視乎就很清楚它的執(zhí)行順序了~~~!
從上面的代碼,我們可以看得出來:我們要做的事情就是:加1顯示然后停一秒···加1顯示然后停一秒····無限循環(huán)下去
我們發(fā)生的事情generator就是:
var delayCount = $$_builder_$$_0.Delay(function () {
doCount();
return $$_builder_$$_0.Bind(Jscex.Async.sleep("1000"), function () {
return $$_builder_$$_0.Normal();
});
});
我們要循環(huán)的就是delayCount,所以我們把它放到一個loop當中去:
var loopCount = $$_builder_$$_0.Loop(
function () {
return true;
},
null,
delayCount,
false
);
其中,第一個參數(shù)就是while(true),他標志這函數(shù)什么時候退出循環(huán)。所以比如while(i<3), 它就會編譯成function(){return i<3;}
然后:
var countAsync = $$_builder_$$_0.Start(this, loopCount);
這行代碼的主要作用是 把這個loop作為一個task賦給Jscex.Async.Task的_delegate,
可想而知,在這種架構的基礎上,可以輕松實現(xiàn)N個loop,就有了異步隊列~~~~
比如:
var executeAsyncQueue = eval(Jscex.compile("async", function () {
while (true) {
$await(countAsync())
$await(otherAsync())
$await(Jscex.Async.sleep(1000));
}
}))
executeAsyncQueue().start();
最后,執(zhí)行countAsync ().start().整個流程就是這樣子的,但是到現(xiàn)在為止,我們還沒有進入Jscex內(nèi)核當中去看一看它是怎么實現(xiàn)這些循環(huán)和中轉的······
或者你根據(jù)上面的思路寫出一個偽Jscex出來?我想這個寫的過程可以幫你更好的理解Jscex的模式。
請關注:
浙公網(wǎng)安備 33010602011771號