在 AJAX 中处理增量服务器响应(在 JavaScript 中)
我有基于服务器响应更新页面的 AJAX 应用程序.AJAX服务器响应所基于的命令需要很长时间才能生成完整的响应,但是一旦计算出来它就会发送部分信息.此部分响应/部分信息以突发"形式发送,并且每个突发的时间和大小是不可预测的.将命令输出流式传输到 Web 浏览器(到 AJAX 请求)的 CGI 脚本(在 Perl 中)已打开自动刷新.
I have AJAX app which updates page based on server response. The command that AJAX server response is based on takes long time to generate full response, but it sends partial information as soon as it is calculated. This partial response / partial info is send in "burst", and time and size of each burst is unpredictable. CGI script (in Perl) that streams command output to web browser (to AJAX request) has autoflush turned on.
服务器响应基于外部命令的输出.'time cmd >/dev/null' 平均给出大约 10.0 秒,'time cmd | head >/dev/null' 给出不到 0.1 秒(例如数据).所有数据都是单次调用此外部命令的结果.
The server response is based on output of external command. While 'time cmd > /dev/null" gives around 10.0 seconds on average, 'time cmd | head > /dev/null' gives less than 0.1 seconds (for example data). All data is result of single call to this external command.
情况如下(ASCII-艺术图如下):
client | | server
--------- ---------
request -
->
/- response
/ .
/ .
/ /- .
<-/ / .
/ .
/ /- [end]
<-/ /
/
/
<-/
我有几个关于这个问题的问题.
I have a few questions about this problem.
注意:服务器端在 Perl 中作为 CGI 脚本完成,我更希望看到(也)解决方案,而不使用像 jQuery 这样的 JavaScript 库/框架.
Note: server side is done as CGI script in Perl, and I would prefer to see (also) solution without using JavaScript library / framework like jQuery.
AJAX 应用服务器端使用的命令输出是基于行的.每组线,以一种定义的线开始,以另一种线结束,由独立且不可更改的数据组成.我应该只是将来自命令的响应流式传输为text/plain"并在客户端用 JavaScript 进行处理,还是应该在服务器上预处理数据,并使用application/json"mimetype 将整个数据块作为 JSON 发送?
The output of command used by server side of AJAX app is line based. Each group of lines, beginning with one defined kind of line, and ending with other kind of line, consist of independend and unchangeable data. Should I just stream response from a command as 'text/plain' and do processing in JavaScript on client side, or should I pre-process data on server, and send whole chunks of data as JSON using 'application/json' mimetype?
可能会发生服务器一次发送的大量数据之后很快就会有另一块数据的情况.如何处理 onreadystatechange
处理程序被调用而先前的调用没有完成工作的情况?我应该使用全局变量作为信号量,还是将状态变量作为处理程序参数传递(好吧,使用 xhr.onreadystatechange = function() { handleRequest(xhr, state) }
)?
It might happen that large chunk of data send at once by server is followed soon by another chunk of data. How to deal with situation when onreadystatechange
handler is invoked while previous invocation didn't finished work? Should I use global variable as semaphore, or pass state variable as handler parameter (well, use xhr.onreadystatechange = function() { handleRequest(xhr, state) }
)?
我应该使用text/plain"还是application/json",或者可能是multipart/x0mixed-replace"?注意:这个应用程序应该可以在(几乎)任何浏览器中运行.
Should I use 'text/plain' or 'application/json', or perhaps 'multipart/x0mixed-replace' for this? Note: this app should work in (alomst) any browser.
如何处理仅在收到完整响应后才调用 onReadyStateChange 的网络浏览器(JavaScript 引擎)(所以我看不到 xhr.readyState == 3
即部分响应不止一次)?好吧,除了使用一些 JavaScript 框架.
How to deal with web browser (JavaScript engines) which invoke onReadyStateChange only after receiving complete response (so I don't see xhr.readyState == 3
i.e. partial response more than once)? Well, beside using some JavaScript framework.
如何处理不完整的响应(在这种情况下意味着不完整的行).
How to deal with incomplete responses (which in this situation mean incomplete lines).
我应该发送响应结束标记,还是依靠计数器来检查我们是否收到了所有数据,或者我可以简单地依靠检测 xhr.readyState == 4
?
Should I send end of response marker, or rely on counter to check if we received all data, or can I simply rely on detecting xhr.readyState == 4
?
即使是部分回应也会有所帮助.
Even partial response would be helpful.
推荐答案
我认为 Comet 是您的解决方案所需的一部分.您还可以(如果我没记错的话)签出 Bayeux Protocol,它是由 Dojo 基金会实施.整个事情还是很新的(尽管其中一些可能在第一个 HTML5 实现中是可能的).
I think Comet is part of what you need for your solution. You can additionally (if I got that right) checkout the Bayeux Protocol which was implemented by the Dojo Foundation. The whole thing is still very new (though some of it might be possible with the first HTML5 implementations).
除此之外,您可能还必须实施轮询方法.另一个问题是,客户端 JavaScript 解释器可以处理多少数据.您是否有可能以某种方式分页"您的数据,这样您就不会遇到请求处理仍在处理而另一个响应已经到来的问题?
Besides that you would probably have to implement the polling approach. The other question is, how much data the client side JavaScript interpreter can handle. Is there any possibility for you to somehow "page" your data so that you won't have the problem of request handling still processing while aother response comes in already?
相关文章