网格中的实时数据 - 更好的方法

时间:2012-05-05 11:08:06

标签: jqgrid

什么是在网格中显示实时数据(证券交易所,天气......)的更好方法? 我用这个方法:

setInterval(function(){
      jQuery("#list1").trigger('reloadGrid');
}, 5000);

1 个答案:

答案 0 :(得分:16)

我觉得你的问题非常有趣。我认为这个问题对许多其他用户来说可能很有意思。所以来自我的+1。

setInterval的用法在常见的浏览器独立案例中以最佳方式联系我。我应该将setInterval的结果保存在变量中,以便能够使用clearInterval来阻止它。

[{current:true}]的另一个小改进是使用trigger(有关详细信息,请参阅the answer)作为var $grid = jQuery("#list1"), timer; timer = setInterval(function () { $grid.trigger('reloadGrid', [{current: true}]); }, 5000); 的第二个参数:

beforeProcessing

它将在重新加载网格时保存选择。

现在许多新的网络浏览器都支持WebSocket。因此,如果Web浏览器支持它,最好使用这种方式。如果数据没有在服务器上更改并且阻止服务器永久池化,那么可以跳过不需要的网格重新加载。

在我看来,一种更常见的方式也非常有趣。如果可以使用网格数据的最后更改的某种时间戳,则可以验证数据是否被更改。可以在服务器上使用ETag或一些通用的附加方法。

填充jqGrid的success的当前jQuery.ajax回调允许您使用jqXHR.satus回调修改服务器响应,但它是不允许您根据xhr.status值停止jqGrid刷新(在当前的jqGrid代码中它将是textStatus)。对jqGrid代码the line的小修改将允许您在服务器上未更改数据的情况下停止jqGrid刷新。可以为st测试"notmodified"(jqGrid的当前代码中的jqXHR.satus)或xhr.status(当前jqGrid代码中的prmNames: { nd:null }){{{ 3}}。使用该方案非常重要,您应使用ETag选项并设置Cache-Control: private, max-age=0success(请参阅304here和{{3其他信息)。

更新:我尝试根据我的上一个建议创建演示项目,发现它并不像我上面描述的那么容易。不过我做到了。困难在于因为人们无法从jQuery.ajax中的服务器响应中看到304代码。原因是here

中的以下位置
  

对于由用户代理导致的 304 Not Modified 响应   生成的条件请求用户代理必须像服务器一样   使用适当的内容给出了 200 OK 响应。用户代理   必须允许作者请求标头覆盖自动缓存   验证(例如 If-None-Match If-Modified-Since ),在这种情况下    304 Not Modified 响应必须通过。

因此,您可以在服务器响应的$.ajax XMLHttpRequest处理程序中找到 200 OK 状态,而不是 304 Not Modified 。似乎ETag从缓存中获得完整响应,包括所有HTTP头。因此,我决定更改缓存数据的分析,只是将ETag从上一个HTTP响应保存为新的jqGrid参数,并使用保存的数据测试新响应的beforeProcessing

我看到你使用PHP(我不会使用:-()。但是我可以阅读和理解PHP代码。我希望你能以同样的方式阅读C#代码并理解主要思想。所以你将能够在PHP中实现相同的功能。

现在我描述一下我的所作所为。首先,我修改了使用if ($.isFunction(ts.p.beforeProcessing)) { ts.p.beforeProcessing.call(ts, data, st, xhr); } 回调的jqGrid源代码的here

if ($.isFunction(ts.p.beforeProcessing)) {
    if (ts.p.beforeProcessing.call(ts, data, st, xhr) === false) {
        endReq();
        return;
    }
}

beforeProcessing

它允许从beforeProcessing返回false以跳过数据刷新 - 跳过数据处理。我在演示中使用的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"); }

$("#isProcessed").text("Processed");

$("#isProcessed").text("Processing skipped!!!");或行"Processed"在div中设置"Processing skipped!!!"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请求:

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响应:

HTTP/1.1 200 OK

所以如果数据未更改,则不会从服务器传输数据。如果数据发生更改,HTTP标头将以ETag启动,并包含$grid1.trigger('reloadGrid', [{ current: true}]);个新修改数据以及数据页本身。

可以使用"刷新"手动刷新网格数据。导航器的按钮或使用"启动自动刷新"按钮,每秒执行loadui: "disable"。该页面看起来像

enter image description here

我用颜色框标记了页面底部最重要的部分。如果有一个"Processed"选项,则在拉动服务器期间根本看不到网格上的任何更改。如果有人评论了一个人会看到的选项"正在加载......" div很短的时间,但没有网格会闪烁

开始"自动清新"一个人会看到如下图片

enter image description here

如果要更改第一个网格中的某一行,则第二个网格将在一秒钟内更改,其中一个将显示"Processing skipped!!!"文本,该文本将在一秒内更改为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); } 文本。< / p>

服务器端的相应代码(我使用ASP.NET MVC)主要是以下

beforeProcessing

我希望代码的主要思想也适用于那些不仅使用ASP.NET MVC的人。

您可以下载项目XMLHttpRequest specification

更新:我发布了the lines以允许false通过返回{{1}}值来中断服务器响应的处理。主要的jqGrid代码中已包含相应的更改(请参阅here)。所以jqGrid的下一个版本将包含它。