1. 程式人生 > 程式設計 >Javascript非同步執行不按順序解決方案

Javascript非同步執行不按順序解決方案

案例分析:

比如執行懶載入時候,onscroll 事件觸發多次事件時候會呼叫多次 ajax 回撥事件,由於每個事件返回先後次序並不能保證和觸發前一致,所以在資料響應返回後所新增的資料順序就很在 push 到陣列上順序不一致。

例子1:

var res = [];
   function response(data) {
     res.push( data );
}
// ajax(..)是某個庫中提供的某個Ajax函式 
ajax( "http://some.url.1",response ); 
ajax( "http://some.url.2",response );

這裡的併發“程序”是這兩個用來處理 Ajax 響應的 response() 呼叫。它們可能以任意順 序執行。

我們假定期望的行為是 res[0] 中放呼叫 "http://some.url.1" 的結果,res[1] 中放呼叫 "http://some.url.2" 的結果。有時候可能是這樣,但有時候卻恰好相反,這要視哪個調 用先完成而定。

這種不確定性很有可能就是一個競態條件 bug。

解決辦法

var res = [];
function response(data) {
     if (data.url == "http://some.url.1") {
       res[0] = data;
     }
     else if (data.url == "http://some.url.2") {
       res[1] = data;
     } 
}
// ajax(..)是某個庫中提供的某個Ajax函式 
ajax( "http://some.url.1",response );

不管哪一個 Ajax 響應先返回,我們都要通過檢視 data.url(當然,假定從伺服器總會返 回一個!)判斷應該把響應資料放在 res 陣列中的什麼位置上。res[0] 總是包含 "http:// some.url.1" 的結果,res[1] 總是包含 "http://some.url.2" 的結果。通過簡單的協調,就 避免了競態條件引起的不確定性。

例子2:

var a,b;
   function foo(x) {
     a = x * 2;
     baz(); 
   }
   function bar(y) {
     b = y * 2;
     baz(); 
   }
   function baz() {
     console.log(a + b);
   }
// ajax(..)是某個庫中的某個Ajax函式 
ajax( "http://some.url.1",foo ); 
ajax( "http://some.url.2",bar );

在這個例子中,無論 foo() 和 bar() 哪一個先被觸發,總會使 baz() 過早執行(a 或者 b 仍處 於未定義狀態);但對 baz() 的第二次呼叫就沒有問題,因為這時候 a 和 b 都已經可用了。

要解決這個問題有多種方法。這裡給出了一種簡單方法:

var a,b;
function foo(x) {
     a = x * 2;
     if (a && b) {
       baz();
     } 
}
function bar(y) {
     b = y * 2;
     if (a && b) {
       baz();
     } 
}
function baz() {
     console.log( a + b );
}
// ajax(..)是某個庫中的某個Ajax函式 
ajax( "http://some.url.1",foo );
ajax( "http://some.url.2",bar );

包裹baz()呼叫的條件判斷if (a && b)傳統上稱為門(gate),我們雖然不能確定a和b 到達的順序,但是會等到它們兩個都準備好再進一步開啟門(呼叫 baz())。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。