javascript - 為什麼jQuery的remove不是同步的?
phpcn_u1582
phpcn_u1582 2017-05-19 10:16:13
0
3
571

頁面上有一按鈕如下

<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裡才能得到想要的效果…?

phpcn_u1582
phpcn_u1582

全部回覆(3)
某草草

這個問題問得確實是有點…… 咋一看以為代碼故意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();
    },

一定也阻塞

为情所困

應該是你阻塞了線程 使得圖形渲染也'卡'住了

即便button已從dom樹中刪除。

但是圖形沒有把新的、不存在button的dom樹重新繪製。

淡淡烟草味

之前是我想的簡單了,應該是跟樓下說的一樣,畫面渲染卡住了。
例如在func();之前列印一下日誌:

console.log(func);

出現輸出標識之後就卡住了,等到sleep執行完才把完整內容顯示出來:

sleep執行時頁面被阻塞完全不能操作了,同時CPU佔用非常高(因為這個循環理論上沒有間隔,)可能是這個導致被卡住了吧。

熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!