2016-10-18 38 views
0

這個問題出現在一個巨大而複雜的應用程序中,但它可以在一個簡單的用例中重現:如果主瀏覽器線程繁忙, 由web worker發送的XHR將阻塞,直到主瀏覽器線程空閒,就好像工作人員是一個正常的功能,掛起0ms超時, 等待其主線程啓動。實際上並沒有發生什麼:正在發生併發,我們可以從日誌條目的時間戳 中看出,但似乎只有在主Javascript線程是空閒時才能完成XMLHttpRequest的實際發送。首先,我們認爲這種行爲僅限於Internet Explorer,但實際上它只是以這種方式出現,因爲IE在我們特定的 用例中慢得多,因此主瀏覽器線程保持更長時間的忙碌狀態。這種非併發行爲實際上出現在我嘗試過的所有瀏覽器中(IE, Chrome,Firefox)。瀏覽器的行爲並不完全相同:有時他們在open()調用上阻塞,有時他們在send()上阻塞,有時他們聲稱send()及時完成,但使用HTTP調試器如Fiddler顯示數據實際上並未發送到 服務器,直到主瀏覽器線程完成其長時間運行的任務。在發送XHR時,Web工作人員不是真正的併發?

所以我希望有人能告訴我爲什麼這樣,以及是否有任何方法讓網絡工作者以恰當的併發方式發送XHR。順便說一句,我 已經知道,總體問題的關鍵是主要的Javascript線程是多麼繁忙,所以請不要告訴我解決這個問題;我們也在 上工作,但是長期運行的任務是在客戶的應用程序中對基於JS的非常複雜的用戶界面進行迴流,所以我們在這裏可以做的事情僅限於 。

這個攝製情況說明了什麼問題:

<html> 
<body> 
<div id="test"></div> 
<script> 
worker = new Worker('worker.js'); 
// Wait for 2 seconds to be as sure as we can be that it has downloaded and installed the worker code 

setTimeout(proceed, 2000); 

function proceed() { 

    worker.postMessage(""); 
    console.log("Message sent to worker: " + new Date().getTime()); 

    // Now tie up the JS thread 
    setTimeout(function() { 
     console.log("Started crazy pointless loop: " + new Date().getTime()); 
     for (var i = 0; i < 500000; i++) { 
      var j = i/17, 
       k = j * j, 
       l = k/123; 
      document.getElementById("test").innerHTML = "l = " + l; 
     } 

     console.log("Finished crazy pointless loop: " + new Date().getTime()); 
    }, 0); 
} 
</script> 
</body> 
</html> 

和worker.js文件:

addEventListener('message', function(e) { 

    var xhr = new XMLHttpRequest(); 
    xhr.onreadystatechange = function() { 
     if (xhr.readyState < 4) return; 
     console.log("Response received: " + new Date().getTime()); 
    } 
    console.log("Ready to open XHR: " + new Date().getTime()); 
    xhr.open("GET", "dummy.html?nocache=" + new Date().getTime(), true); 
    console.log("XHR opened: " + new Date().getTime()); 
    xhr.send(); 
    console.log("XHR sent: " + new Date().getTime()); 

}, false); 
+0

我沒有任何數據支持此,所以這不是一個答案。但是我強烈懷疑所有瀏覽器都使用主線程來限制給定域的併發連接數。對於任何給定的域,HTTP 1.1指定不超過2個。儘管大多數瀏覽器並不尊重極限,但它們都具有我期望通過主線程執行的上限。有關更多信息,請參閱http://stackoverflow.com/questions/985431/max-parallel-http-connections-in-a-browser。 –

回答

1

你會更好,從工人同步發送XHR因爲你已經在一個單獨的線程中運行:

addEventListener('message', function(e) { 
    var xhr = new XMLHttpRequest(); 
    console.log("Ready to open XHR: " + new Date().getTime()); 
    xhr.open("GET", "dummy.html?nocache=" + new Date().getTime(), false); // false makes it synchronous 
    console.log("XHR opened: " + new Date().getTime()); 
    xhr.send(); 
    console.log("Response received: " + new Date().getTime()); 
}, false);