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

标签 jqgrid

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

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 }选项并设置ETagCache-Control: private, max-age=0(有关其他信息,请参见hereherehere)。

更新:我尝试根据我的最后建议创建演示项目,发现它并不像我上面描述的那么容易。尽管如此,我还是成功了。困难在于因为无法从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/

相关文章:

javascript - JQGRID - 使用按钮删除行

javascript - 在 jqgrid 中过滤时是否可以发送字段类型?

java - jqgrid 将 Jqgrid 数据发布回 Action 类

c# - 设置默认值内联添加Jqgrid

jquery - 仅 IE 9 setSelection 中的错误不会滚动到所选行

javascript - 如何修复 jqgrid 列选择器垃圾布局

jqgrid - 在 jqGrid 中加载时触发客户端过滤

javascript - JQGrid 'Change' dataevent 在更改函数内更改网格行数据后未触发

jquery - 启用/禁用 jqGrid 中的自定义按钮

jquery - jqGrid 具有用户自定义的高级搜索和 addJSONData 填充