天天看點

艾偉:Ajax基石腳本異步并發調用參數傳遞

    在Ajax開發架構中,最基本的劃分是伺服器端和用戶端。伺服器端相對來說比較簡單,隻要是可以開發動态網頁的語言都可以勝任;用戶端浏覽器就是JScript/JavaScript的天下了,好像沒有看到有VBScript做的Ajax用戶端庫,就算它隻支援IE。由于用戶端依賴于腳本并運作在浏覽器中,似乎比伺服器端的可實作和可管理性還要差些。

艾偉:Ajax基石腳本異步并發調用參數傳遞

function foo()

艾偉:Ajax基石腳本異步并發調用參數傳遞
艾偉:Ajax基石腳本異步并發調用參數傳遞
艾偉:Ajax基石腳本異步并發調用參數傳遞

{

艾偉:Ajax基石腳本異步并發調用參數傳遞

    var param = 100;

艾偉:Ajax基石腳本異步并發調用參數傳遞

    window.setTimeout(function()

艾偉:Ajax基石腳本異步并發調用參數傳遞
艾偉:Ajax基石腳本異步并發調用參數傳遞
艾偉:Ajax基石腳本異步并發調用參數傳遞
艾偉:Ajax基石腳本異步并發調用參數傳遞

        intervalRun(param);

艾偉:Ajax基石腳本異步并發調用參數傳遞

    }, 0);

艾偉:Ajax基石腳本異步并發調用參數傳遞

    param = 0;

艾偉:Ajax基石腳本異步并發調用參數傳遞

}

艾偉:Ajax基石腳本異步并發調用參數傳遞
艾偉:Ajax基石腳本異步并發調用參數傳遞

function intervalRun(times)

艾偉:Ajax基石腳本異步并發調用參數傳遞
艾偉:Ajax基石腳本異步并發調用參數傳遞
艾偉:Ajax基石腳本異步并發調用參數傳遞
艾偉:Ajax基石腳本異步并發調用參數傳遞

    alert(times);

艾偉:Ajax基石腳本異步并發調用參數傳遞

    我們執行foo,會得到什麼樣的alert結果呢?100? or 0?,答案是:0。其實寫過内嵌函數就知道,這裡要真确的傳入100,需要這樣改寫foo方法:

艾偉:Ajax基石腳本異步并發調用參數傳遞
艾偉:Ajax基石腳本異步并發調用參數傳遞
艾偉:Ajax基石腳本異步并發調用參數傳遞
艾偉:Ajax基石腳本異步并發調用參數傳遞
艾偉:Ajax基石腳本異步并發調用參數傳遞
艾偉:Ajax基石腳本異步并發調用參數傳遞

    var __param = param;

艾偉:Ajax基石腳本異步并發調用參數傳遞
艾偉:Ajax基石腳本異步并發調用參數傳遞
艾偉:Ajax基石腳本異步并發調用參數傳遞
艾偉:Ajax基石腳本異步并發調用參數傳遞
艾偉:Ajax基石腳本異步并發調用參數傳遞

        intervalRun(__param);

艾偉:Ajax基石腳本異步并發調用參數傳遞
艾偉:Ajax基石腳本異步并發調用參數傳遞
艾偉:Ajax基石腳本異步并發調用參數傳遞

// 這樣添加一個變量來存儲param就可以了,這下執行foo得到的alert結果就是:100。

    上面這個修正本身沒有問題,可是如果我在并發執行的情況下,就可能又有新的問題。示例代碼:

艾偉:Ajax基石腳本異步并發調用參數傳遞

function doTick()

艾偉:Ajax基石腳本異步并發調用參數傳遞
艾偉:Ajax基石腳本異步并發調用參數傳遞
艾偉:Ajax基石腳本異步并發調用參數傳遞
艾偉:Ajax基石腳本異步并發調用參數傳遞

    var tick = new Date().getTime();

艾偉:Ajax基石腳本異步并發調用參數傳遞

    var __tick = tick;

艾偉:Ajax基石腳本異步并發調用參數傳遞

    var foo = function()

艾偉:Ajax基石腳本異步并發調用參數傳遞
艾偉:Ajax基石腳本異步并發調用參數傳遞
艾偉:Ajax基石腳本異步并發調用參數傳遞
艾偉:Ajax基石腳本異步并發調用參數傳遞

        GetTick(__tick);

艾偉:Ajax基石腳本異步并發調用參數傳遞

    };

艾偉:Ajax基石腳本異步并發調用參數傳遞

    window.setTimeout(foo, 3000);

艾偉:Ajax基石腳本異步并發調用參數傳遞
艾偉:Ajax基石腳本異步并發調用參數傳遞
艾偉:Ajax基石腳本異步并發調用參數傳遞

function GetTick(tick)

艾偉:Ajax基石腳本異步并發調用參數傳遞
艾偉:Ajax基石腳本異步并發調用參數傳遞
艾偉:Ajax基石腳本異步并發調用參數傳遞
艾偉:Ajax基石腳本異步并發調用參數傳遞

    // to do something depend on tick parameter

艾偉:Ajax基石腳本異步并發調用參數傳遞

    當我們在調用doTick方法時,如果以小于3000ms的頻率并發,将會導緻前一次的tick變量被後面執行的執行過程修改的問題,進而導緻GetTick方法取到錯誤的tick參數。也就是說必須把doTick方法看成一個,需要"本身執行時間+3000ms"才能運作完的方法,然後再保證并行的執行doTick方法才不會出錯。這樣的限制條件顯然是不可接受的,那麼我們該怎麼辦呢?

    其實我們隻需要使用内嵌函數自身幫助我們傳遞參數就行了,修改後的示例如下:

艾偉:Ajax基石腳本異步并發調用參數傳遞
艾偉:Ajax基石腳本異步并發調用參數傳遞
艾偉:Ajax基石腳本異步并發調用參數傳遞
艾偉:Ajax基石腳本異步并發調用參數傳遞
艾偉:Ajax基石腳本異步并發調用參數傳遞
艾偉:Ajax基石腳本異步并發調用參數傳遞
艾偉:Ajax基石腳本異步并發調用參數傳遞
艾偉:Ajax基石腳本異步并發調用參數傳遞
艾偉:Ajax基石腳本異步并發調用參數傳遞
艾偉:Ajax基石腳本異步并發調用參數傳遞

        var __tick = foo.params[0];

艾偉:Ajax基石腳本異步并發調用參數傳遞
艾偉:Ajax基石腳本異步并發調用參數傳遞
艾偉:Ajax基石腳本異步并發調用參數傳遞

    foo.params = [tick];

艾偉:Ajax基石腳本異步并發調用參數傳遞

    window.setTimeout(foo, 0);

艾偉:Ajax基石腳本異步并發調用參數傳遞

    由于内嵌函數構造出一個Closure Scope,它将幫組我們儲存參數的Context,使我們獲得真正的"異步并發調用參數傳遞"效果。

    注意:Closure Scope是JScript程式設計中危險的進階技術,使用不當極易造成IE Memory Leak。