什么是在网格中显示实时数据(证券交易所,天气......)的更好方法?
我用这个方法:
setInterval(function(){
jQuery("#list1").trigger('reloadGrid');
}, 5000);
Run Code Online (Sandbox Code Playgroud)
Ole*_*leg 16
我觉得你的问题非常有趣.我认为这个问题对许多其他用户来说可能很有意思.所以来自我的+1.
setInterval在常见的浏览器独立案例中,使用接缝是最好的方法.一个原因应该是保存setInterval变量中的结果以便能够用clearInterval它来阻止它.
另一个小的改进是使用[{current:true}](参见答案的详细信息)作为第二个参数trigger:
var $grid = jQuery("#list1"), timer;
timer = setInterval(function () {
$grid.trigger('reloadGrid', [{current: true}]);
}, 5000);
Run Code Online (Sandbox Code Playgroud)
它将在重新加载网格时保存选择.
许多新的Web浏览器现在都支持WebSocket.因此,如果Web浏览器支持它,最好使用这种方式.在这种情况下,如果服务器上的数据没有更改,并且阻止了服务器的永久池,则可以跳过不需要的网格重新加载.
在我看来,一种更常见的方式也非常有趣.如果可以使用网格数据的最后更改的某种时间戳,则可以验证数据是否被更改.可以在服务器上使用ETag或一些通用的附加方法.
填充jqGrid 的jQuery.ajax当前成功回调允许您使用实现回调来修改服务器响应,但它不允许您根据值停止jqGrid刷新(它将在当前的jqGrid代码中).对jqGrid代码行的小修改将允许您在服务器上未更改数据的情况下停止jqGrid刷新.可以测试(在当前的jqGrid代码中)或测试(在当前的jqGrid代码中)304.这一点很重要,要使用你应该使用方案选项,并设置和(见这里,这里和这里了解更多信息).beforeProcessingjqXHR.satusxhr.statustextStatusst"notmodified"jqXHR.satusxhr.statusprmNames: { nd:null }ETagCache-Control: private, max-age=0
更新:我试图根据我的最后建议创建演示项目,并发现它并不像我上面描述的那么容易.不过我做到了.困难是因为人们无法从jQuery.ajax中的服务器响应中看到304代码.原因是XMLHttpRequest规范中的以下位置
对于由用户代理生成的条件请求而导致的304 Not Modified响应,用户代理必须表现为服务器使用适当的内容给出200 OK响应.用户代理必须允许作者请求标头覆盖自动缓存验证(例如,If-None-Match或If-Modified-Since),在这种情况下, 必须传递304 Not Modified响应.
于是人们看到200个OK的内部状态success的处理$.ajax,而不是304未修改来自服务器的响应.似乎XMLHttpRequest从缓存中获取完整响应,包括所有HTTP头.因此,我决定更改缓存数据的分析,只是ETag将最后一个HTTP响应保存为新的jqGrid参数,并ETag使用保存的数据测试新响应.
我看到你使用PHP(我不使用:-().但是我可以阅读和理解PHP代码.我希望你能以同样的方式阅读C#代码并理解主要思想.所以你将能够在PHP中实现相同的功能.
现在我描述一下我做了什么.首先,我修改了使用beforeProcessing回调的jqGrid源代码行
if ($.isFunction(ts.p.beforeProcessing)) {
ts.p.beforeProcessing.call(ts, data, st, xhr);
}
Run Code Online (Sandbox Code Playgroud)
至
if ($.isFunction(ts.p.beforeProcessing)) {
if (ts.p.beforeProcessing.call(ts, data, st, xhr) === false) {
endReq();
return;
}
}
Run Code Online (Sandbox Code Playgroud)
它将允许返回false beforeProcessing以跳过刷新数据 - 跳过数据处理.beforeProcessing我在演示中使用的实现基于以下用法ETag:
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");
}
Run Code Online (Sandbox Code Playgroud)
我用来直观地指示来自服务器的数据用于填充网格的div中的行$("#isProcessed").text("Processed");或行$("#isProcessed").text("Processing skipped!!!");集"Processed"或"Processing skipped!!!"文本.
在演示中,我显示了两个具有相同数据的网格.我用的第一个网格用于编辑数据.第二个网格每秒从服务器提取数据.如果服务器上的数据未更改,则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
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
因此,如果数据未更改,则不会从服务器传输任何数据.如果数据已更改,则HTTP标头将与新数据本身一起启动HTTP/1.1 200 OK并包含ETag新修改数据.
可以使用导航器的"刷新"按钮手动刷新网格数据,也可以使用每秒执行$grid1.trigger('reloadGrid', [{ current: true}]);一次的"启动自动刷新"按钮.页面看起来像

我用颜色框标记了页面底部最重要的部分.如果有一个loadui: "disable"选项,则在拉动服务器期间根本看不到网格上的任何更改.如果有人评论选项会看到"加载..."div很短的时间,但没有网格会闪烁.
在"自动清新"开始后,人们将看到如下图所示

如果要更改第一个网格中的某一行,则第二个网格将在一秒内更改,一个将看到"Processed"文本将再次更改为"Processing skipped!!!"文本.
服务器端的相应代码(我使用的是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);
}
Run Code Online (Sandbox Code Playgroud)
我希望代码的主要思想也适用于那些不仅使用ASP.NET MVC的人.
您可以在此处下载该项目.
更新:我发布了功能请求,允许beforeProcessing通过返回false值来中断服务器响应的处理.主要的jqGrid代码中已包含相应的更改(请参阅此处).所以jqGrid的下一个版本将包含它.