2016-06-22 50 views
1

我知道有類似的話題,但我無法找到以下問題的答案。爲什麼第一段代碼執行回調,而第二段不執行回調。當單線程時,javascript如何接收請求後的回調?

var XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest; 
var xmlHttp = new XMLHttpRequest(); 
xmlHttp.onreadystatechange = function() { 
    console.log("Request is ready"); 
} 
xmlHttp.open("GET", "www.google.com", true); 

var result = 0; 

while(1 < 5) { 
} 

在上面的代碼中打印出Request is ready。但使用以下代碼:

setTimeout(function() { 
    console.log("Test") 
    }, 5) 

    while (1 < 5) { 

    } 

Test未打印。爲什麼發生這種情況?我認爲onreadystatechange會在請求準備就緒時執行這個函數,但是因爲我們有一個無限循環,所以活套不會檢查隊列(因爲活套循環在主線程中並且很忙)。這個邏輯適用於第二個例子,但不是第一個例子。顯然我錯過了一些東西。

在此先感謝。

回答

2

在第一種情況下沒有異步事件:open觸發第一個狀態更改並且同步調用onreadystatechange回調。

"Request is ready"日誌完成之前循環進入。

如果添加xmlHttp.send並調用非緩存的URL,則會注意到不會爲其他更改調用回調,因爲這些回調並非真正異步。

+1

是的。 onreadystatechange事件只會在第一次更改時被調用。其他調用,例如請求完成時,您不會再獲得其他事件。 – GolezTrol

+0

非常感謝。但是,在我目前正在完成的工作完成之後,這種改變會被髮送到隊列中。很顯然我不太對。所以當我打開這個函數時,會發送這個動作到隊列中,但是這個動作會立即執行嗎? – DPM

+0

@DPM是的,事件隊列不用於第一次更改。更近期的API在處理事件的方式上更一致,規則是可以是異步的東西必須始終是異步的(請參閱[fetch](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch)爲例)。在過去,許多開發人員認爲,出於性能方面的考慮,最好避免回調隊列(例如,jQuery最近剛剛修復,以便Defferred *總是被異步解析)。 –

相關問題