2008-12-27 18 views
1

我試圖實現一個使用XMLHttpResponse對象的彗星樣式,長查詢連接。 這個想法是保持一個開放的連接到服務器,當服務器可用時發送數據(僞造推送)。一旦XHR對象完成,我需要產生一個新的等待任何新的數據。實現自復位XMLHttpRequest對象

下面是一段代碼,其中概述了一個可行的解決方案,但正如評論所說,只是因爲我需要擺脫超時。

window.onload = function(){ 
    XHR.init(); 
} 


XHR = { 
    init: function() { 
     this.xhr = new XMLHttpRequest(); 
     this.xhr.open("GET", "proxy.php?salt="+Math.round(Math.random()*10000), true); 
     this.xhr.onreadystatechange = this.process.bind(this); 
     this.xhr.send(null); 
    }, 
    process: function() { 
     if(this.xhr.readyState == 4) { 

      // firebug console 
      console.log(this.xhr.responseText); 

      // ** Attempting to create new XMLHttpRequest object to 
      // replace the one that's just completed 
      // doesn't work without the timeout 
      setTimeout(function() { this.init() }.bind(this), 1000); 
     } 
    } 
} 


Function.prototype.bind = function(obj) { 
    var method = this; 
    return function() { 
     return method.apply(obj, arguments); 
    } 
} 


// proxy.php - a dummy that keeps the XHR object waiting for a response 
<?php 
$rand = mt_rand(1, 10); 
sleep($rand); 
echo date('H:i:s').' - '.$rand; 

我認爲這個問題可能是你無法刪除它自己的事件處理程序(過程)的對象(XHR)如這裏的情況。尤其是因爲處理程序中的'this'綁定到一個包含我試圖刪除的對象(xhr)的對象(XHR)。 有點圓!

任何人都可以幫忙嗎?上面的例子是我能得到的最接近的例子。

回答

1

只需使用jQuery和做這樣的事情:

function getData() { 
    $.getJSON(someUrl, gotData); 
    } 

    // Whenever a query stops, start a new one. 
    $(document).ajaxStop(getData, 0); 
    // Start the first query. 
    getData(); 

slosh例子做到這一點(因爲它是非常彗星的服務器)。

+0

這回答'如何做'問題,但不是'它是如何工作'的問題。 我將不得不在周圍的jQuery源中找出答案。具體來說,如何引發ajaxStop事件。 – meouw 2008-12-31 14:47:45

0

你在做什麼是有效的投票,爲什麼使它比需要更復雜,只是每隔幾秒輪詢一次?或者每秒鐘,你真正保存了多少時間,這真的很重要,如果你有很多用戶,你將在服務器端佔用很多插槽。

+0

與每次請求都會導致一次或多次數據庫命中的大量輪詢相比,擁有大量套接字更容易,更少資源密集。 – 2011-08-16 06:50:31

0

但是要真正嘗試和回答你的問題,刪除不是這個東西的方法是設置一個定時器來調用刪除的函數,這樣它就不會被刪除。

0

@stu

在這個應用程序的響應時間是關鍵 - 其實最重要的是,所有的客戶端更新的同時(或儘量接近)

關閉連接數量將相當有限〜50max和更改之間的時間間隔可能是幾分鐘。

如果使用輪詢,它將需要非常短〜100ms,這將導致大量不必要的請求(這對於我拼湊在一起的小型php socket服務器來說是很昂貴的 - 我知道,我知道python對服務器來說會更好,但我不太清楚)

+0

呃,我很難理解你談論的規模。一般來說,我認爲企業/最壞情況,對我來說,python並不比php或其他任何東西都好。問題在於網絡服務器正在分化一個進程,你可能想要避免這種情況。 – stu 2008-12-28 22:18:15

0

你可能根本不應該使用XMLHTTPRequest。

幾年前,XMLHTTPRequest早已爲人所知,我創建了一個用於普通瀏覽器的聊天程序。與聊天窗口在一個框架中,數據來自一個永遠不會結束的CGI腳本。每當有新的數據時,我就發送它,並立即顯示在客戶端。

我想你可以使用類似的話今天:

  • 建立在你的頁面的功能,將做更新。
  • 創建一個IFRAME,你可以把它無形的,如果你想
  • 將IFRAME的源腳本生成的數據
  • 的數據可以在SCRIPT標籤封裝。如果我沒有記錯,瀏覽器在試圖評估它之前需要獲取腳本標記的全部內容。致電您的更新功能:

    <script type="text/javascript">myupdate("mydata");</script> 
    
  • 即使您沒有要發送的內容,也請每隔5秒發送一個空格來重置瀏覽器的超時時間。
  • 如果我沒記錯的話,你必須在交易開始發送1K左右的數據在瀏覽器,填補了預取緩衝(也許這在今天的瀏覽器增加)
0

你可能有一個更輕鬆地實現再利用,將在abort()方法:

XHR = { 
    init: function() { 
     if (!this.xhr) { // setup only once 
      this.xhr = new XMLHttpRequest(); 
      this.xhr.onreadystatechange = this.process.bind(this); 
     } 
     this.xhr.abort(); // reset xhr 
     this.xhr.open(/*...*/); 
     this.xhr.send(null); 
    }, 
    process: function() { 
     if(this.xhr.readyState == 4) { 

      // firebug console 
      console.log(this.xhr.responseText); 

      // start next round 
      this.init(); 
     } 
    } 
}; 

@meouw [評論]

如果你摹(我猜你有一個緩存問題(Math.random()沒有解決),或者你沒有標記先前請求發送了什麼(每次都重發相同的數據)。

+0

此解決方案與原始問題相同。 XHR處理程序立即重複返回最後的結果。 我認爲這是因爲舊的或未更新的對象仍然掛在 – meouw 2008-12-28 15:59:56

0

只需在init函數內添加xhr = null即可。 xhr將被分配一個新的連接,因此不會採用先前的HTTPRequest值。

init: function() { 
     xhr = null; 
     this.xhr = new XMLHttpRequest(); 
     this.xhr.open("GET", "proxy.php?salt="+Math.round(Math.random()*10000), true); 
     this.xhr.onreadystatechange = this.process.bind(this); 
     this.xhr.send(null); 
    },