頁面上有一按鈕如下
<button onclick="index.testClick()" >开始</button>
該頁面對應的js腳本如下
var index = {
testClick: function () {
index.createBtn(function() {
index.sleep(10000);
});
},
sleep: function (n) {
var start = new Date().getTime();
while (true) {
if(new Date().getTime() - start > n)
break;
}
},
createBtn: function (func) {
var button = $('<button>测试</button>');
button.bind("click",function(){
button.remove();
func();
});
$('body').prepend(button);
},
};
為什麼點擊開始按鈕再點擊測試按鈕之後,測試按鈕實際上要sleep(是在同步的$.ajax請求上註意到的,這裡用循環模擬)之後才移除?把sleep包到setTimeout裡才能得到想要的效果…?
某草草2017-05-19 10:18:13
這個問題問得確實是有點…… 咋一看以為代碼故意sleep了10秒然而題主看不懂,透過上面評論區的撕逼大概知道是在問什麼了……
這東東跟瀏覽器UI線程有關,瀏覽器是單線程的(這個線程一般就叫瀏覽器UI線程)。
《高效能JavaScript》第六章 快速回應的使用者介面,有這麼多兩段話:
大多數瀏覽器有一個單獨的處理進程,它由兩個任務所共用: JavaScript 任務和使用者介面更新任務。 每個時刻只有其中的一個操作得以執行, 也就是說當 JavaScript程式碼執行時使用者介面無法對輸入產生反應,反之亦然。或者說,當 JavaScript 運行時,使用者介面就被「鎖定」了。管理好 JavaScript 運行時間對網頁應用的效能很重要。
JavaScript和UI更新共享的進程通常稱做」瀏覽器UI執行緒」。 UI執行緒的工作是基於一個簡單的佇列系統,任務會儲存到佇列中直到行程空閒。一旦空閒,隊列中下一個任務就被重新被提取出來並運行。這些任務要么是運行JS程式碼,要么執行UI更新,包括重繪和重排。
function(){
button.remove();
func();
}
這是點擊事件的處理函數,js移除DOM節點後,func()馬上接著運行,10秒後進程空閒,才會運行下一個任務,更新用戶界面,這時候按鈕才會在頁面中消失。
上面另一個答案評論區的問題,『為什麼添加的時候就不會有這種現象』
添加的函數是這樣的,
createBtn: function (func) {
var button = $('<button>测试</button>'); //生成button
button.bind("click",function(){ //给button绑点击事件
button.remove();
func();
});
$('body').prepend(button); //把button加到body上
},
這個過程並沒有運行func(),試試把這個函數移出來,改成這樣
createBtn: function (func) {
var button = $('<button>测试</button>');
button.bind("click",function(){
button.remove();
});
$('body').prepend(button);
func();
},
一定也阻塞
淡淡烟草味2017-05-19 10:18:13
之前是我想的簡單了,應該是跟樓下說的一樣,畫面渲染卡住了。
例如在func();之前列印一下日誌:
console.log(func);
出現輸出標識之後就卡住了,等到sleep執行完才把完整內容顯示出來:
sleep執行時頁面被阻塞完全不能操作了,同時CPU佔用非常高(因為這個循環理論上沒有間隔,)可能是這個導致被卡住了吧。