Jak*_*ski 14 javascript ajax streaming comet xmlhttprequest
客户端请求来自服务器的网页.然后Clent要求进行额外的计算; 服务器执行一系列计算并在可用时立即发送部分结果(文本格式,每行包含单独的完整项目).客户端使用服务器提供的信息更新网页(使用JavaScript和DOM).
这似乎适合Ajaxpatterns站点的HTTP Streaming(当前版本)模式.
问题是如何以跨浏览器(浏览器不可知)的方式进行,最好不使用JavaScript框架,或使用像jQuery这样的轻量级框架.
问题始于以跨浏览器方式生成XMLHttpRequest,但我认为主要项目是并非所有浏览器都能onreadystatechange从XMLHttpRequest正确实现; 并非所有浏览器都onreadystatechange在每个服务器刷新上调用事件(顺便说一下.如何在CGI脚本中强制刷新服务器(在Perl中)?).Ajaxpatterns上的示例代码通过使用计时器处理此问题; 如果我发现部分响应,我应该丢弃定时器解决方案onreadystatechange吗?
添加11-08-2009
当前解决方案:
我使用以下函数创建XMLHttpRequest对象:
function createRequestObject() {
var ro;
if (window.XMLHttpRequest) {
ro = new XMLHttpRequest();
} else {
ro = new ActiveXObject("Microsoft.XMLHTTP");
}
if (!ro)
debug("Couldn't start XMLHttpRequest object");
return ro;
}
Run Code Online (Sandbox Code Playgroud)
如果我使用一些(最好是轻量级)JavaScript框架,比如jQuery,如果用户选择不安装jQuery,我希望有后备.
我使用以下代码启动AJAX; setInterval因为某些浏览器onreadystatechange仅在服务器关闭连接后调用(可能需要长达数十秒),而不是在服务器刷新数据(大约每秒或更多次)之后调用.
function startProcess(dataUrl) {
http = createRequestObject();
http.open('get', dataUrl);
http.onreadystatechange = handleResponse;
http.send(null);
pollTimer = setInterval(handleResponse, 1000);
}
Run Code Online (Sandbox Code Playgroud)
该handleResponse功能是最复杂的一个,但它的草图如下所示.可以做得更好吗?如何使用一些轻量级JavaScript框架(如jQuery)?
function handleResponse() {
if (http.readyState != 4 && http.readyState != 3)
return;
if (http.readyState == 3 && http.status != 200)
return;
if (http.readyState == 4 && http.status != 200) {
clearInterval(pollTimer);
inProgress = false;
}
// In konqueror http.responseText is sometimes null here...
if (http.responseText === null)
return;
while (prevDataLength != http.responseText.length) {
if (http.readyState == 4 && prevDataLength == http.responseText.length)
break;
prevDataLength = http.responseText.length;
var response = http.responseText.substring(nextLine);
var lines = response.split('\n');
nextLine = nextLine + response.lastIndexOf('\n') + 1;
if (response[response.length-1] != '\n')
lines.pop();
for (var i = 0; i < lines.length; i++) {
// ...
}
}
if (http.readyState == 4 && prevDataLength == http.responseText.length)
clearInterval(pollTimer);
inProgress = false;
}
Run Code Online (Sandbox Code Playgroud)
实际上,您链接到的解决方案根本不是 AJAX。他们称之为 HTTP Streaming,但它本质上只是长轮询。
在他们链接到的示例中,您可以使用 firebug 轻松地亲自查看。打开Net面板——没有XHR条目,但加载原始页面只需要10多秒的时间。这是因为他们在幕后使用 PHP 来延迟 HTML 的输出。这就是长轮询的本质 - HTTP 连接保持打开状态,并且定期发回的 HTML 是 javascript 命令。
不过,您可以选择使用 setTimeout() 或 setInterval() 完全在客户端进行轮询
一个 jQuery 示例
<script type="text/javascript">
$(document).ready(function()
{
var ajaxInterval = setInterval( function()
{
$.getJSON(
'some/servie/url.ext'
, { sample: "data" }
, function( response )
{
$('#output').append( response.whatever );
}
);
}, 10000 );
});
</script>
Run Code Online (Sandbox Code Playgroud)