2015-08-21 18 views
0

如果由於腳本中某些長時間運行的方法而導致一堆UIEvents排隊,並且在方法I setTimeout(myfunc, 0)的末尾,myfunc相對於以前排隊的處理程序被調用的順序事件?在所有之前排隊的事件得到處理之後,它是否保證被調用?setTimeout和UIEvent命令

回答

2

瀏覽器中的大部分事件都是通過中央事件隊列按先進先出順序處理的。某些UI事件(如mousemove事件)已摺疊,因此您可以獲取最新狀態,而不一定是所有中間事件。

所以,問題是當鼠標事件進入JS事件隊列時。我不確定這是如何工作的,所以我建立了一對測試演示。我發現的答案取決於。如果UI事件是佔用JS線程的東西,那麼看起來其他UI事件不會進入定時器前面的隊列,但是如果UI事件結束並且其他一些操作(不在UI上)生豬CPU,然後evnets按正確的FIFO順序排隊。所以,看起來「取決於」(在Chrome中,這是我迄今爲止測試過的)。

我將張貼鏈接到演示在第二...

This demo表明,如果CPU上拱活動不響應按鈕點擊後,setTimeout()之前發生的那麼其他按鈕點擊是時間表大火將setTimeout()之前得到處理:

long 
click 
click 
click 
timeout 

但是,this demo其中CPU霸佔發生在按鈕單擊事件處理程序本身就說明了相反的。在setTimeout()之前發生的點擊事件在計劃之前並未得到處理。現在

long 
timeout 
click 
click 
click 

,我都在Firefox運行這些發現,在這兩種情況下的Firefox在處理FIFO的順序事件(在他們實際發生的順序)。對於上面的第二個演示,這與Chrome不同。

現在,我在IE瀏覽器中運行這兩種瀏覽器,發現IE始終在UI事件之前處理setTimeout()--與Firefox和Chrome不同。

因此,這些測試在三種不同的瀏覽器中顯示了三種不同的結果。

總結結果:

Browser  Hog CPU in Event Handler  Hog CPU after Event Handler 
--------------------------------------------------------------------- 
Chrome 44  timeout first (not FIFO)  FIFO clicks first 
Firefox 39  FIFO clicks first    FIFO clicks first 
IE 11   timeout first (not FIFO)  timeout first (not FIFO) 

僅供參考,下面是豬在按鈕單擊事件處理程序的CPU測試情況:

document.getElementById("test").addEventListener("click", function() { 
    log("click"); 
}); 

document.getElementById("long").addEventListener("click", function() { 
    log("long"); 
    setTimeout(function() { 
     log("timeout"); 
    }, 1900) 
    // hhog the CPU here before the event handler finishes 
    var t = Date.now(); 
    while (Date.now() - t < 2000) {} 
}); 

而且,這裏的測試用例豬按鈕客戶端事件處理程序完成後的CPU。

document.getElementById("test").addEventListener("click", function() { 
    log("click"); 
}); 

document.getElementById("long").addEventListener("click", function() { 
    log("long"); 

    // schedule a setTimeout 
    setTimeout(function() { 
     log("timeout"); 
    }, 1900) 

    // hog the CPU, but after the UI event has finished 
    setTimeout(function() { 
     // spin for 2 seconds to hog the JS thread 
     var t = Date.now(); 
     while (Date.now() - t < 2000) {} 
    }, 1); 
}); 
+0

哇,多奇怪。換句話說,至少在Chrome中看起來像,UI事件處理程序阻止其他UI事件在運行時插入到隊列中。 – Andy

+0

@安迪 - 除非我的測試存在一些缺陷,否則看起來如此。有些東西告訴我必須有一些規範的一部分,談論這應該如何工作,但我還沒有找到它。這可能是尚未明確規定的行爲之一。 – jfriend00

+0

沒錯。我希望Firefox的行爲方式最終成爲規範 – Andy

0

在做了一些測試後,我不得不編輯我的答案,因爲我錯了。是的,UI事件優先於超時。對於超時,無論按照什麼順序設置,UI事件都會首先發生。

+1

但是,在他稱爲'setTimeout'之前排隊的所有事件是不是先執行? – Barmar

+0

準確地@Barmar,這就是我所問的。當然,我知道我的超時將在長時間運行後執行。 – Andy

+0

在我運行的測試中,超時或事件設置的順序似乎並不重要。超時被UI事件阻止,所以我編輯了我的答案以確保準確性。 –