想實現 彈框3s後自動隱藏,我設定如下程式碼:
document.getElementById("alertMessageSel").style.display = "block";
document.getElementById("alertMessage").innerHTML = "两次输入手机号不一致!";
var t = Date.now();
var t1 = Date.now() + 100;
while(t1 - t <= 3000) {
t1 = Date.now();
};
document.getElementById("alertMessage").innerHTML = "";
document.getElementById("alertMessageSel").style.display = "none";
單步調試沒有問題,會順序執行,我指的是打斷點,效果和我想像一樣,但是不打斷點直接運行就不會出現這個效果。
我想到了js在運行過程中運行應該有自己的執行方式。
2.想知道其中的運作機制,想了解如何實現,達到我預期的效果。
高洛峰2017-06-26 10:52:14
什麼是阻塞機制
Js阻塞機制,跟Js引擎的單執行緒處理方式有關,每個window一個JS執行緒。所謂單線程,在某個特定的時刻只有特定的程式碼能夠被執行,並且阻塞其它的程式碼。
由於瀏覽器是事件驅動的(Event driven),因此瀏覽器中很多行為是異步(Asynchronized)的,很容易有事件被同時或連續觸發。當非同步事件發生時,會建立事件並放入執行佇列中,等待目前程式碼執行完成之後再執行這些程式碼,如滑鼠點擊事件發生、計時器觸發事件發生、XMLHttpRequest完成回呼這些事件,都會被放入執行隊列中等待。
關於Js的阻塞機制,可以看下面一段程式碼,一般,我們會認為,這段程式碼會log出來0,1,2
for(var i=0;i<3;i++){
setTimeout(function(){
console.log(i);
}, 10);
}
而實際上,這段程式碼log出來的結果是 3,3,3。這是js新手很容易遇到的問題,具體原因就是因為for迴圈的阻塞機制。在上面的程式碼中,setTimeout這個定時器需要等待for迴圈執行完成,而for迴圈執行完成了之後,i已經為3了,此時才開始執行setTimeout,因此console.log(i)會是3。
至於為什麼i會是3,請回顧for迴圈的執行順序,當i為2的時候,滿足迴圈條件,執行程式碼區塊,然後i++,此時i為3,不滿足迴圈條件,不執行程式碼區塊,循環停止。
對於for循環,記住,是在不滿足條件的情況下停止循環,對於以上程式碼,可以看出,i=3的時候才不滿足。
怎麼解決事件阻塞
其實,阻塞作為js引擎的處理方式,我們最好不要想著解決“阻塞”,而是讓我們想執行的程式碼,插入到“主執行緒”中。這麼說比較不易理解,還是以上面的程式碼為例,直接上程式碼好了
for(var i=0;i<3;i++){
(function(i){
setTimeout(function(){
console.log(i);
}, 10);
})(i)
再上面的程式碼中,我們加了一個立即執行的匿名函數,並且將for迴圈的i當作實參傳入進去。這樣,setTimeout就會立即執行,而不會等待(這裡小編不太了解細節,就不多說了,大概猜測為新開了一個臨時的線程,立即執行匿名函數,然後再立即切換回來) 。