什么是在网格中显示实时数据(证券交易所,天气等)的更好方法?
我使用这种方法:
setInterval(function(){
jQuery("#list1").trigger('reloadGrid');
}, 5000);
最佳答案
我觉得你的问题很有趣。我认为这个问题对于许多其他用户可能很有趣。所以我+1。setInterval
的用法为我提供了与普通浏览器无关的最佳方法。原因之一是将setInterval
的结果保存在变量中,以便能够使用clearInterval
停止它。
还有一个小的改进是使用[{current:true}]
(有关详细信息,请参见the answer)作为trigger
的第二个参数:
var $grid = jQuery("#list1"), timer;
timer = setInterval(function () {
$grid.trigger('reloadGrid', [{current: true}]);
}, 5000);
在重新加载网格时,它将保存选择。
现在许多新的Web浏览器都支持WebSocket。因此,如果网络浏览器支持,最好使用这种方式。这样一来,如果服务器上的数据没有更改,就可以跳过不必要的网格重新加载,并防止服务器永久池化。
在我看来,一种更常见的方式也很有趣。如果可以使用网格数据最后一次更改的某种时间戳,则可以验证数据是否已更改。为此,可以在服务器上使用ETag或某种常规的其他方法。
填充jqGrid的success当前的jQuery.ajax回调允许您使用实现
beforeProcessing
回调来修改服务器响应,但不允许您停止基于jqXHR.satus
值的jqGrid刷新(它将为xhr.status
在当前的jqGrid代码中)。只需对jqGrid代码的the line进行少量修改,就可以在服务器上的数据不变的情况下停止jqGrid刷新。可以为textStatus
测试st
(在jqGrid当前代码中为"notmodified"
),也可以为304测试jqXHR.satus
(在当前jqGrid代码中为xhr.status
)。重要的是要使用此方案,应使用prmNames: { nd:null }
选项并设置ETag
和Cache-Control: private, max-age=0
(有关其他信息,请参见here,here和here)。更新:我尝试根据我的最后建议创建演示项目,发现它并不像我上面描述的那么容易。尽管如此,我还是成功了。困难在于因为无法从jQuery.ajax内部的服务器响应中看到304代码。原因是XMLHttpRequest specification中的以下位置
对于由用户代理产生的304未修改的响应
生成的条件请求,用户代理必须像服务器一样
给出200 OK并带有适当的内容。用户代理
必须允许作者请求标头覆盖自动缓存
验证(例如If-None-Match或If-Modified-Since),在这种情况下
304未修改的响应必须通过。
因此,在服务器的响应中,在
success
的$.ajax
处理程序内部看到200 OK状态,而不是304未修改。看来XMLHttpRequest
仅从缓存(包括所有HTTP标头)中获取完整响应。因此,我决定更改缓存数据的分析,仅将最后一个HTTP响应中的ETag
保存为新的jqGrid参数,并使用保存的数据测试新响应的ETag
。我看到您使用PHP(但我不使用:-()。尽管如此,我仍然可以阅读和理解PHP代码。希望您能够以相同的方式阅读C#代码并理解主要思想,因此您将能够在PHP中实现相同的功能。
现在,我描述我的所作所为。首先,我修改了jqGrid源代码的the lines,该源代码使用来自
if ($.isFunction(ts.p.beforeProcessing)) {
ts.p.beforeProcessing.call(ts, data, st, xhr);
}
至
if ($.isFunction(ts.p.beforeProcessing)) {
if (ts.p.beforeProcessing.call(ts, data, st, xhr) === false) {
endReq();
return;
}
}
它将允许从
beforeProcessing
返回false以跳过数据刷新-跳过数据处理。我在演示中使用的beforeProcessing
实现基于用法beforeProcessing
:beforeProcessing: function (data, status, jqXHR) {
var currentETag = jqXHR.getResponseHeader("ETag"), $this = $(this),
eTagOfGridData = $this.jqGrid('getGridParam', "eTagOfGridData");
if (currentETag === eTagOfGridData) {
$("#isProcessed").text("Processing skipped!!!");
return false;
}
$this.jqGrid('setGridParam', { eTagOfGridData: currentETag });
$("#isProcessed").text("Processed");
}
在div中,行
ETag
或行$("#isProcessed").text("Processed");
设置了$("#isProcessed").text("Processing skipped!!!");
或"Processed"
文本,我曾经用这种方法直观地表明来自服务器的数据已用于填充网格。在演示中,我显示两个具有相同数据的网格。我用于编辑数据的第一格。第二个网格每秒提取一次来自服务器的数据。如果服务器上的数据未更改,则HTTP流量如下所示
HTTP请求:
GET http://localhost:34336/Home/DynamicGridData?search=false&rows=10&page=1&sidx=Id&sord=desc&filters= HTTP/1.1
X-Requested-With: XMLHttpRequest
Accept: application/json, text/javascript, */*; q=0.01
Referer: http://localhost:34336/
Accept-Language: de-DE
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; LEN2)
Host: localhost:34336
If-None-Match: D5k+rkf3T7SDQl8b4/Y1aQ==
Connection: Keep-Alive
HTTP响应:
HTTP/1.1 304 Not Modified
Server: ASP.NET Development Server/10.0.0.0
Date: Sun, 06 May 2012 19:44:36 GMT
X-AspNet-Version: 4.0.30319
X-AspNetMvc-Version: 2.0
Cache-Control: private, max-age=0
ETag: D5k+rkf3T7SDQl8b4/Y1aQ==
Connection: Close
因此,如果不更改数据,则不会从服务器传输任何数据。如果更改了数据,则HTTP标头将以
"Processing skipped!!!"
开头,并包含新修改的数据的HTTP/1.1 200 OK
以及数据本身的页面。可以使用导航器的“刷新”按钮手动刷新网格数据,也可以使用“启动自动刷新”按钮每秒刷新一次
ETag
。该页面看起来像我在页面底部用颜色框标记了最重要的部分。如果选择一个
$grid1.trigger('reloadGrid', [{ current: true}]);
选项,则在拉动服务器的过程中根本看不到网格上的任何更改。如果有人评论了一个选项,即在很短的时间内看到“正在加载...” div,但是没有网格包含将闪烁。启动“自动刷新”后,大多数人会看到如下图所示的图片
如果要更改第一个网格中的某行,则第二个网格将在一秒钟内更改,并且将看到
loadui: "disable"
文本,此文本将在多秒钟后更改为"Processed"
文本。服务器端的相应代码(我使用ASP.NET MVC)主要是以下代码
public JsonResult DynamicGridData(string sidx, string sord, int page, int rows,
bool search, string filters)
{
Response.Cache.SetCacheability (HttpCacheability.ServerAndPrivate);
Response.Cache.SetMaxAge (new TimeSpan (0));
var serializer = new JavaScriptSerializer();
... - do all the work and fill object var result with the data
// calculate MD5 from the returned data and use it as ETag
var str = serializer.Serialize (result);
byte[] inputBytes = Encoding.ASCII.GetBytes(str);
byte[] hash = MD5.Create().ComputeHash(inputBytes);
string newETag = Convert.ToBase64String (hash);
Response.Cache.SetETag (newETag);
// compare ETag of the data which already has the client with ETag of response
string incomingEtag = Request.Headers["If-None-Match"];
if (String.Compare (incomingEtag, newETag, StringComparison.Ordinal) == 0) {
// we don't need return the data which the client already have
Response.SuppressContent = true;
Response.StatusCode = (int)HttpStatusCode.NotModified;
return null;
}
return Json (result, JsonRequestBehavior.AllowGet);
}
我希望对于不仅仅使用ASP.NET MVC的人,代码的主要思想也应该清楚。
您可以下载项目here。
更新:我发布了the feature request,以允许
"Processing skipped!!!"
通过返回beforeProcessing
值来中断服务器响应的处理。相应的更改已包含在主jqGrid代码中(请参见here)。因此,下一版的jqGrid将包括它。
关于jqgrid - 网格中的实时数据-更好的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10461237/