2012-06-26 70 views
1

我有一個AJAX密集型應用程序,需要快速或同時發送多個AJAX請求。以下代碼僅僅是用於發送我在整個應用中使用的AJAX POST調用的簡單包裝。有兩個注意事項:在離線時排隊多個AJAX請求,當連接返回時發送

1)我希望能夠在提出請求之前測試用戶的互聯網連接,所以如果連接中斷,我可以通知他們。 2)如果他們的連接關閉,他們繼續使用應用程序,這會產生更多的AJAX調用,我想排隊這些調用並在連接返回後一個一個地發送它們。

連接檢查和排隊工作,但是當用戶重新聯機時,只有一些請求被髮送到服務器,並且他們似乎被髮送出它們的原始順序。我錯過了什麼?爲什麼不是所有的請求都被髮送,爲什麼他們沒有按順序?

而在任何人注意之前,我已經看到關於這個主題涉及jQuery的一些其他解決方案。我不反對使用這些,我只是想了解爲什麼這個代碼不工作。提前致謝。

window.connectionState = true 
window.xhrQueue = [] 
window.pingInterval 

function xhrPost(url, packet, before, after) { 
    if (!url || typeof(url) !== "string") { 
    console.log("invalid url supplied in xhr call.") 
    return false 
    } 

    var mainRequest = function() { 
    var xhr= new XMLHttpRequest() 

    if (typeof(after) === "function") { 
     xhr.onreadystatechange = function(){ 
     if (xhr.readyState == 4) { 
      after(xhr) 
      return true 
     } 
     } 
    } 

    if (typeof(before) === "function") { 
     before() 
    } 

    xhr.open("POST",url,true) 
     if (packet) { 
     xhr.send(JSON.stringify(packet)) 
     } 
     else { 
     xhr.send() 
     } 
    } 

    ping(mainRequest) 
} 

function ping(mainRequest) { 

    // Create pingXhr to test connection 
    var pingXhr = new XMLHttpRequest() 

    pingXhr.onreadystatechange = function(){ 
    // If pingXhr comes back successfully... 
    if (pingXhr.readyState == 4) { 
     if (pingXhr.status == 200) { 
     // If pingXhr comes back from being down, update user 
     if (window.connectionState !== true) { 
      setTimeout(function() { alert("And we're back! Your connection seems to be working now. Keep editing.") }, 1) 
     } 
     // If there are requests waiting, send them in order, then remove them 
     if (window.xhrQueue.length > 0) { 
      for (var i in window.xhrQueue) { 
      ping(window.xhrQueue[i]) 
      window.xhrQueue.splice(i, 1) 
      clearInterval(window.pingInterval) 
      } 
     } 
     // Otherwise, just make the singular request 
     else { 
      mainRequest() 
     } 
     // Reset xhrQueue since stuff is successful, change connection to true, and unset onbeforeunload message 
     window.xhrQueue = [] 
     window.connectionState = true 
     } 
     // If there was a problem with the request 
     else { 
     // Notify the user their internet is down 
     if (window.connectionState === true) { 
      setTimeout(function() { alert("It seems you have momentarily lost internet connectivity.") }, 1) 
     } 
     // If there are no requests in the xhrQueue, create the timeout. Otherwise, just add to the queue 
     if (window.xhrQueue.length === 0) { 
      window.pingInterval = setInterval(function(){ ping() }, 3000) 
     } 
     // Add the request to the xhrQueue to be processed in order 
     if (typeof(mainRequest) === "function") { 
      window.xhrQueue.push(mainRequest) 
     } 
     window.connectionState = false 
     } 
    } 
    } 
    pingXhr.open("GET","/some/url/here",true) 
    pingXhr.send() 
} 

回答

1

看起來你正在使用推()放置在隊列中的條目,然後使用拼接送他們一次一個()在一個循環刪除它們。這不太可能正常工作 - 它會跳過它們中的一些/大部分,因爲當您迭代它們時,拼接會修改數組中的索引。

如果您更改循環以始終關閉第一個元素,它會更好。

編輯添加:你可能不想在這裏做一個for-in循環。在迭代時修改對象的鍵通常不是一個好主意。

類似:

while (window.xhrQueue.length > 0) { 
    ping(window.xhrQueue[0]); 
    window.xhrQueue.splice(0, 1); 
} 

,而不是試圖同時運行所有排隊的請求或者,你可以有onreadystatechange的處理搶掉隊列中的下一個項目,只是發送該請求。

+0

這兩個答案都是正確的,但馬克的建議,雖然在對比for-in循環非常有幫助。謝謝! – Sean

1

這將是因爲你立刻全部解僱他們,有些人需要更長的時間才能回到其他人,所以他們的處理者會先跑步。

我建議你使用回調發送下一個

相關問題