溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

解決Javascript異步執(zhí)行不按順序問(wèn)題

發(fā)布時(shí)間:2020-07-29 12:41:22 來(lái)源:億速云 閱讀:149 作者:小豬 欄目:web開(kāi)發(fā)

小編這次要給大家分享的是解決Javascript異步執(zhí)行不按順序問(wèn)題,文章內(nèi)容豐富,感興趣的小伙伴可以來(lái)了解一下,希望大家閱讀完這篇文章之后能夠有所收獲。

案例分析:

比如執(zhí)行懶加載時(shí)候,onscroll 事件觸發(fā)多次事件時(shí)候會(huì)調(diào)用多次 ajax 回調(diào)事件,由于每個(gè)事件返回先后次序并不能保證和觸發(fā)前一致,所以在數(shù)據(jù)響應(yīng)返回后所添加的數(shù)據(jù)順序就很在 push 到數(shù)組上順序不一致。

例子1:

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

這里的并發(fā)“進(jìn)程”是這兩個(gè)用來(lái)處理 Ajax 響應(yīng)的 response() 調(diào)用。它們可能以任意順 序運(yùn)行。

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

這種不確定性很有可能就是一個(gè)競(jìng)態(tài)條件 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(..)是某個(gè)庫(kù)中提供的某個(gè)Ajax函數(shù) 
ajax( "http://some.url.1", response ); 
ajax( "http://some.url.2", response );

不管哪一個(gè) Ajax 響應(yīng)先返回,我們都要通過(guò)查看 data.url(當(dāng)然,假定從服務(wù)器總會(huì)返 回一個(gè)!)判斷應(yīng)該把響應(yīng)數(shù)據(jù)放在 res 數(shù)組中的什么位置上。res[0] 總是包含 "http:// some.url.1" 的結(jié)果,res[1] 總是包含 "http://some.url.2" 的結(jié)果。通過(guò)簡(jiǎn)單的協(xié)調(diào),就 避免了競(jìng)態(tài)條件引起的不確定性。

例子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(..)是某個(gè)庫(kù)中的某個(gè)Ajax函數(shù) 
ajax( "http://some.url.1", foo ); 
ajax( "http://some.url.2", bar );

在這個(gè)例子中,無(wú)論 foo() 和 bar() 哪一個(gè)先被觸發(fā),總會(huì)使 baz() 過(guò)早運(yùn)行(a 或者 b 仍處 于未定義狀態(tài));但對(duì) baz() 的第二次調(diào)用就沒(méi)有問(wèn)題,因?yàn)檫@時(shí)候 a 和 b 都已經(jīng)可用了。

要解決這個(gè)問(wèn)題有多種方法。這里給出了一種簡(jiǎn)單方法:

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(..)是某個(gè)庫(kù)中的某個(gè)Ajax函數(shù) 
ajax( "http://some.url.1", foo );
ajax( "http://some.url.2", bar );

包裹baz()調(diào)用的條件判斷if (a && b)傳統(tǒng)上稱(chēng)為門(mén)(gate),我們雖然不能確定a和b 到達(dá)的順序,但是會(huì)等到它們兩個(gè)都準(zhǔn)備好再進(jìn)一步打開(kāi)門(mén)(調(diào)用 baz())。

看完這篇關(guān)于解決Javascript異步執(zhí)行不按順序問(wèn)題的文章,如果覺(jué)得文章內(nèi)容寫(xiě)得不錯(cuò)的話(huà),可以把它分享出去給更多人看到。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI