1. 程式人生 > 實用技巧 >JS 同步與非同步程式設計

JS 同步與非同步程式設計

JS同步與非同步程式設計

JS是單執行緒的, js就是個傻子, 腦子一根筋, 做著當前的這件事情, 沒有完成之前絕不會做下一件事情

JS中的兩種程式設計思想

同步

上一件事情沒有完成, 繼續處理上一件事情, 只有上一件事情完成了, 才會做另一件事情(JS中大部分都是同步程式設計的)

for(var i = 0; i < 10000; i ++){
    if  i == 9999(){
        console.log("迴圈結束了~~")
    }
    console.log("ok")
}

-> 迴圈結束了~~
-> ok

for迴圈就是同步程式設計的, 只有迴圈結束後, 才會繼續執行下面的程式碼

while(1){

}
console.log("ok")

永遠都不會執行 console.log("ok"), 因為上面的迴圈是死迴圈, 永遠都不會結束

非同步

規劃要做一件事情, 但是不是當前立馬去執行這件事情, 需要等一定的時間, 這樣的話, 我們不會等著它執行, 而是繼續執行下面的操作, "只有當下面的事情都處理完成了", 只有當下面的事情都處理了, 才會返回頭處理之前的事情; 如果下面的事情並沒有處理完成, 不管之前的事情有沒有到時間, 都踏踏實實的給我等著

實現方法

在JS中非同步程式設計只有四種情況:

  • 定時器都是非同步程式設計的
  • 所有的事件都是非同步程式設計的
  • Ajax讀取資料的時候, 我們一般都設定為非同步程式設計
  • 回撥函式也都是非同步程式設計的

定時器

var n = 0;
window.setTimeout(function(){
    n++;
    console.log(n);
}, 1000);
console.log(n);

-> 0
-> 1

不立即執行

每一個瀏覽器對於定時器的等待時間都有一個最小的值, 谷歌:5~6ms IE:10~13ms, 如果設定的等待時間小於這個值, 不起作用, 還是需要等到最小時間才執行; 尤其是寫0也不是立即執行.

var n = 0;
window.setTimeout(function(){
    n++;
    console.log(n);
}, 0);
console.log(n);

-> 0
-> 1

不保證準確的執行時間

我們定時器設定的等待時間不一定就是最終執行的時間, 如果定時器之後還有其他的事情正在處理中, 不管定時器的時間有沒有到, 都是不會執行定時器的

var n = 0;
window.setTimeout(function(){
    n++;
    console.log(n);
}, 0);
console.log(n);
while(1){
    n++
}
console.log(n)

-> 0
進入死迴圈, 瀏覽器卡死

任務佇列
var n = 0;
window.setTimeout(function (){
    n += 2;
    console.log(n)
}, 2);

window.setTimeout(function (){
    n += 5;
    console.log(n)
}, 1);

console.log(n);
for(var i =0; i < 10000000; i++){
    
}
console.log(n);

-> 0
-> 0
-> 5
-> 7

任務佇列

任務佇列池

任務 -> 2ms執行

將任務->1ms執行新增到佇列池中, 發現時間更短的在任務佇列中提前排列

任務 -> 1ms執行
任務 -> 2ms執行

執行區

var n = 0;
console.log(n); ->0
執行一千萬次的迴圈, 可能消耗的時間大於20ms也可能小於20ms
console.log(n) -> 0
此時的立即執行的任務都完成了

返回頭
開始按照任務池中的任務佇列的順序開始從上到下執行.

事件

for(var i=0; i<oLis.length;i++){
    oLis[i].onclick = function(){
        console.log(i);
    }
}

-> 3
-> 3
-> 3

使用者點選的時候, 迴圈已經執行完了, i已經變成了3.