2008-12-27 62 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); 
    },