問題描述
客戶端從服務(wù)器請(qǐng)求網(wǎng)頁.然后 Clent 要求進(jìn)行額外的計(jì)算;服務(wù)器執(zhí)行一系列計(jì)算并在部分結(jié)果可用時(shí)立即發(fā)送(文本格式,每行包含單獨(dú)的完整項(xiàng)目).客戶端使用服務(wù)器提供的信息更新網(wǎng)頁(使用 JavaScript 和 DOM).
Client request web page from server. Clent then requests for extra calculations to be done; server performs series of calculations and sends partial results as soon as they are available (text format, each line contains separate full item). Client updates web page (with JavaScript and DOM) using information provided by server.
這似乎適合 HTTP Streaming (當(dāng)前 版本)模式來自 Ajaxpatterns 站點(diǎn).
This seems to fit HTTP Streaming (current version) pattern from Ajaxpatterns site.
問題是如何以跨瀏覽器(與瀏覽器無關(guān))的方式進(jìn)行,最好不使用 JavaScript 框架,或使用一些輕量級(jí)框架,如 jQuery.
The question is how to do it in cross-browser (browser agnostic) way, preferably without using JavaScript frameworks, or using some lightweight framework like jQuery.
問題始于以跨瀏覽器方式生成 XMLHttpRequest,但我認(rèn)為主要是并非所有瀏覽器都能正確實(shí)現(xiàn) onreadystatechange
from XMLHttpRequest;并非所有瀏覽器都會(huì)在每次服務(wù)器刷新時(shí)調(diào)用 onreadystatechange
事件(順便說一句.如何從 CGI 腳本(在 Perl 中)強(qiáng)制服務(wù)器刷新?).Ajaxpatterns 上的示例代碼通過使用計(jì)時(shí)器來處理這個(gè)問題;如果我檢測(cè)到來自 onreadystatechange
的部分響應(yīng),我應(yīng)該放棄計(jì)時(shí)器解決方案嗎?
The problem begins with generating XMLHttpRequest in cross-browser fashion, but I think the main item is that not all browsers implement correctly onreadystatechange
from XMLHttpRequest; not all browsers call onreadystatechange
event on each server flush (BTW. how to force server flush from within CGI script (in Perl)?). Example code on Ajaxpatterns deals with this by using timer; should I drop timer solution if I detect partial response from onreadystatechange
?
添加于 2009 年 8 月 11 日
當(dāng)前解決方案:
我使用以下函數(shù)創(chuàng)建 XMLHttpRequest 對(duì)象:
Current solution:
I use the following function to create XMLHttpRequest object:
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;
}
如果我要使用一些(最好是輕量級(jí)的)JavaScript 框架,比如 jQuery,如果用戶選擇不安裝 jQuery,我希望有備用.
If I were to use some (preferably light-weight) JavaScript framework like jQuery, I'd like to have fallback if user chooses not to install jQuery.
我使用下面的代碼來啟動(dòng) AJAX;使用 setInterval
是因?yàn)槟承g覽器僅在服務(wù)器關(guān)閉連接后(可能需要數(shù)十秒)才調(diào)用 onreadystatechange
,而不是在服務(wù)器刷新數(shù)據(jù)時(shí)(大約每第二次或更頻繁).
I use the following code to start AJAX; setInterval
is used because some browsers call onreadystatechange
only after server closes connection (which can take as long as tens of seconds), and not as soon as server flushes data (around every second or more often).
function startProcess(dataUrl) {
http = createRequestObject();
http.open('get', dataUrl);
http.onreadystatechange = handleResponse;
http.send(null);
pollTimer = setInterval(handleResponse, 1000);
}
handleResponse
函數(shù)是最復(fù)雜的一個(gè),但它的草圖如下所示.可以做得更好嗎?如何使用一些輕量級(jí)的 JavaScript 框架(如 jQuery)來完成?
The handleResponse
function is most complicated one, but the sketch of it looks like the following. Can it be done better? How it would be done using some lightweight JavaScript framework (like 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('
');
nextLine = nextLine + response.lastIndexOf('
') + 1;
if (response[response.length-1] != '
')
lines.pop();
for (var i = 0; i < lines.length; i++) {
// ...
}
}
if (http.readyState == 4 && prevDataLength == http.responseText.length)
clearInterval(pollTimer);
inProgress = false;
}
推薦答案
實(shí)際上,您鏈接到的解決方案根本不是 AJAX.他們稱之為 HTTP 流,但它本質(zhì)上只是長(zhǎng)輪詢.
The solution you linked to is not AJAX at all, actually. They call it HTTP Streaming but it's essentially just long polling.
在他們鏈接到的示例中,您可以很容易地使用 firebug 自己查看.打開網(wǎng)絡(luò)面板 - 沒有 XHR 條目,但加載原始頁面只需 10 多秒.那是因?yàn)樗麄冊(cè)谀缓笫褂?PHP 來延遲 HTML 的輸出.這就是長(zhǎng)輪詢的本質(zhì)——HTTP 連接保持打開狀態(tài),周期性的 HTML 發(fā)回是 javascript 命令.
In the example they link to, you can see for yourself quite easily with firebug. Turn on the Net panel - there are no XHR entries, but it takes just a hair over 10 seconds to load the original page. That's because they're using PHP behind the scenes to delay the output of the HTML. This is the essence of long polling - the HTTP connection stays open, and the periodic HTML sent back is javascript commands.
不過,您可以選擇使用 setTimeout() 或 setInterval() 在客戶端完全進(jìn)行輪詢
You can opt to do the polling completely on the client side, though, with setTimeout() or setInterval()
一個(gè) jQuery 示例
A jQuery example
<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>
這篇關(guān)于“HTTP Streaming"的跨瀏覽器實(shí)現(xiàn)(推)AJAX 模式的文章就介紹到這了,希望我們推薦的答案對(duì)大家有所幫助,也希望大家多多支持html5模板網(wǎng)!