搜尋

首頁  >  問答  >  主體

javascript - 為什麼jQuery的remove不是同步的?

頁面上有一按鈕如下

<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_u1582phpcn_u15822775 天前624

全部回覆(3)我來回復

  • 某草草

    某草草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();
        },

    一定也阻塞

    回覆
    0
  • 为情所困

    为情所困2017-05-19 10:18:13

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

    即便button已從dom樹中刪除。

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

    回覆
    0
  • 淡淡烟草味

    淡淡烟草味2017-05-19 10:18:13

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

    console.log(func);

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

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

    回覆
    0
  • 取消回覆