2012-03-07 48 views
2

我在遇到同步AJAX請求時遇到問題。同步AJAX調用並非真正同步

我正在創建一個Web應用程序,其中有許多按順序調用的AJAX請求,應按嚴格順序返回。我決定只是同步地調用它們,而不是將每個後續請求放入最後一個請求的readystatechange事件處理程序中。

但是,在下面的代碼中,在向添加對DOM的響應之前,將調用alert()

window.addEventListener("load", main, false); 

function main (e) { 

    // Sending synchronous request 
    var request = new XMLHttpRequest(); 
     request.open("GET", fileName, false); 
     request.overrideMimeType("text/xml"); 
     request.send(null); 

    // Receiving response 
    var response = request.responseXML; 

    // Changing XML Tree to corresponding XHTML Tree 
    response = XMLtoXHTML(response); 

    //Adding response to the body 
    document.body.appendChild(response); 

    // Calling alert 
    alert("Hello World"); 

} 

的響應變得其實成功添加到DOM,但只有點擊警報消息OK了。當我使用Safari的腳本調試功能進行漫遊時,在調用alert()之前,響應確實將添加到DOM

有什麼建議嗎?

注意:我遺漏了其他請求。

+0

既然你不使用'onreadystatechange'處理程序,它似乎不太可能在'appendChild'之前調用'alert'。你有沒有同步運行多個AJAX請求的問題,或者這只是一個測試?難道這個元素實際上是被添加的,但是Safari在點擊'alert'後纔會重繪文檔?您是否嘗試過使用Firefox或IE瀏覽器來查看它們是否有不同的功能? – 2012-03-07 20:01:37

+0

良好的通話測試它在不同的平臺上。這似乎是一個只有Safari的問題。我想你是對的異步只是要走的路。 – 2012-03-07 20:08:56

+0

真的,除非您專門試圖阻止用戶在您的請求期間進行交互,或者您正在使用Web工作者,否則應始終運行異步請求。同步請求被阻塞,這意味着在請求完成之前,頁面上沒有其他JS可以運行 - 沒有JS懸停效果,沒有點擊按鈕等 - 只是想如果其中一個請求緩慢或超時...如果你只是想連鎖請求,然而,'onreadystatechange'是要走的路。 – 2012-03-07 20:19:07

回答

3

我想它實際上確實被添加了,在JS返回控制權返回給瀏覽器之前,即在警告窗口關閉之前,您只是看不到更改。如果你不能做一個異步請求(我會建議先),你至少可以做一個單獨的setTimeout ed「線程」的dom更改。

+0

在添加響應之後請求無論在響應中如何,在Safari中返回null,這在其他瀏覽器中似乎不是這樣。 – 2012-03-07 20:11:20

2

它確實已被添加到DOM,但頁面尚未將新元素解析到視圖中。如果我不得不猜測它會因爲警報阻塞當前正在運行的JS線程,webkit將嘗試在此期間執行迴流以提高效率。

測試用例:

function foo() 
{ 
    var div = document.createElement("div"); 
    div.innerHTML = "hi friends"; 
    div.id = "bar"; 
    document.body.appendChild(div); 
    alert(document.getElementById("bar").innerHTML); 
} 

你需要的元素出現在警報出現過嗎?使用此在這種情況下

setTimeout(function(){alert("Hello World");}, 1); 
+0

謝謝大家的快速回復! ^^很好的例子 – 2012-03-07 20:43:05

0

或者使用流量控制庫像Frame.js(或asnyc,flow.js,更多):

Frame(function(next)){ 
    document.body.appendChild(response); 
    next(); 
}); 
Frame(function(next)){ 
    alert("Hello World"); 
    next(); 
}); 
Frame.init();