自动取消jqGrid请求 [英] Automatically canceling jqGrid request

查看:91
本文介绍了自动取消jqGrid请求的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我认为该用户问的是我问的相同问题,但提出该问题的原因有所不同,因此他接受了不同的解决方案.我需要做他最初的要求:

I think this user was asking the same question I'm asking, but the reason driving his question was different, so he accepted a different solution. I need to do what he was originally asking:

自动取消jqgrid请求

我的jqGrid有一个搜索工具栏(输入字段显示在列标题下方,但在数据上方).大多数列都有下拉列表(stype = select),这些下拉列表列出了该列的可用过滤器选项,并在顶部带有全部"选项.用填充我的jqGrid的JSON数据响应的服务器端代码很复杂,因此有些慢,尤其是在过滤条件的方式不多的情况下.这意味着,如果用户选择全部",则可能要过几秒钟才能显示任何结果.这本身就可以,但是如果用户在返回响应之前进行了另一个过滤器选择,则网格不会取消现有请求,也不会提交新请求,因此在之后用户进行第二选择,网格将更新以显示对第一选择的响应.此外,当您更改过滤器选择时,网格会自动更新,因此要使其显示所需的数据,您必须将选择内容更改为其他内容,等待其加载,然后改回来.

My jqGrid has a search toolbar (the input fields that appear below the column headers but above the data). Most of the columns have dropdowns (stype=select) that list the available filter options for that column, with an 'All' option at the top. The server-side code that responds with the JSON data that populates my jqGrid is complex and therefore somewhat slow, especially when there isn't much in the way of filter criteria. This means that if the user selects 'All', it may be several seconds before any results show up. This is fine by itself, but if the user makes another filter selection before the response comes back, the grid does not cancel the existing request, nor does it submit a new one, so at some point after the user makes the second selection, the grid updates to show the response for the first selection. Furthermore, the grid auto-updates when you change the filter selection, so to get it to show the data you wanted, you have to change your selection to something else, wait for that to load, and then change it back.

这是我到目前为止尝试过的:

Here's what I've tried so far:

$(document).ready(setupGrid);

var currentGridRequest;

function setupGrid() {
    var grid = $("#grid").jqGrid({
        ...
        loadError: function(xhr, status, error) {
            currentGridRequest = undefined;
        },
        loadComplete: function(data) {
            currentGridRequest = undefined;
        },
        loadBeforeSend: function(xhr, settings) {
            if (currentGridRequest !== undefined) {
                currentGridRequest.abort();
            }
            currentGridRequest = xhr;
        }
    });
}

我遇到的问题是,如果已经有一个请求在飞行中,则loadBeforeSend事件实际上不会触发.我已经尝试了事件文档页面中的其他事件( http://www.trirand.com/jqgridwiki/doku.php?id=wiki:events ):beforeRequest和jqGridToolbarBeforeSearch都表现出相同的行为.

The problem I have is that the loadBeforeSend event doesn't actually fire if there's already a request in flight. I've tried a other events from the event documentation page (http://www.trirand.com/jqgridwiki/doku.php?id=wiki:events): beforeRequest and jqGridToolbarBeforeSearch both exhibit the same behavior.

我该怎么做才能中止进行中的请求并继续基于用户的最新选择进行搜索?这是jqGrid中的错误吗?我最初是在4.2版上遇到此问题的;我刚刚升级到4.4.4,但这种行为没有改变.

What can I do to abort the in-flight request and proceed with searching based on the user's most recent selection? Is this a bug in jqGrid? I initially encountered this issue on version 4.2; I've just upgraded to 4.4.4 with no change in this behavior.

看看jqGrid代码,如果不更改jqGrid代码本身,我看到的行为似乎是不可避免的. jqGrid在每个请求的开始设置一个标志(ts.grid.hDiv.loading)并在结束时将其清除;设置此标志后,将不会提交新的过滤条件,也不会触发任何事件.

Looking at the jqGrid code, the behavior I'm seeing appears to be unavoidable without changing the jqGrid code itself. jqGrid sets a flag (ts.grid.hDiv.loading) at the beginning of each request and clears it at the end; when this flag is set, new filter criteria will not be submitted and no events will fire.

我还考虑过修改JSON响应,使其包含请求条件,然后编写一些JS代码以将响应与当前条件选择进行比较.如果它们不匹配,我将忽略响应,而不将其呈现到网格中.由于jqGrid甚至没有提交第二组条件,因此该选项不在桌面上(即使我可以解决该问题,我的当前方法似乎也是可取的.)

I also considered modifying my JSON response so that it included the request criteria, and then write some JS code to compare the response to the current criteria selection. If they didn't match, I'd ignore the response and not render it to the grid. Since jqGrid doesn't even SUBMIT the second set of criteria, that option is off the table (and even if I can fix that problem, my current approach seems preferable).

推荐答案

我找到了一种实现自己想要的方法的方法.我在多个地方使用jqGrid(在某些情况下在同一页面上包括多个网格),因此我将其分解为一个函数,该函数可以从任何地方调用,并且包含自己的范围来管理是否存在当前请求;只需将其传递给网格,它将附加所有必要的事件处理程序.请注意,这将覆盖您可能为相关事件定义的所有现有处理程序.

I've found a way to do what I wanted. I use jqGrid in several places (including multiple grids on the same page in a few cases), so I factored it out into a function I can call from anywhere and which contains its own scope for managing whether there is a current request; just pass it a grid and it will attach all of the necessary event handlers. Note that this will overwrite any existing handlers you may have defined for the relevant events.

function applyJqgridHandlers(grid) {
    (function(self, undefined) {
        var currentRequest;
        function abortCurrentRequestIfAny() {
            if (currentRequest !== undefined) {
                currentRequest.abort();
            }
        }
        self.clearCurrentRequest = function() {
            abortCurrentRequestIfAny();
            currentRequest = undefined;
        };
        self.setCurrentRequest = function(xhr) {
            abortCurrentRequestIfAny();
            currentRequest = xhr;
        };
    })(grid.currentRequestHolder = {});

    grid.currentRequestHolder.clearCurrentRequest();
    grid.jqGrid('setGridParam', {
        loadError: function(xhr, status, error) {
            grid.currentRequestHolder.clearCurrentRequest();
        },
        loadBeforeSend: function(xhr, settings) {
            grid.currentRequestHolder.setCurrentRequest(xhr);
        },
        loadComplete: function(data) {
            grid.currentRequestHolder.clearCurrentRequest();
        }
    });
    grid.bind('jqGridToolbarBeforeSearch', function() {
        grid.currentRequestHolder.clearCurrentRequest();
        this.grid.hDiv.loading = false;
    });
};

然后,我只需在setupGrid()的末尾添加对此函数的调用.

Then I simply add a call to this function from the end of setupGrid().

此代码明确清除ts.grid.hDiv.loading标志,该标志不是已发布的jqGrid API的一部分,因此我认为此解决方案相当脆弱.不能保证它将在将来的jqGrid版本中继续使用.如果有人对解决此问题的更好(较不脆弱)的方法有任何建议,我将不知所措. :)

This code explicitly clears the ts.grid.hDiv.loading flag, which is not part of the published jqGrid API, so I consider this solution to be fairly fragile; there's no guarantee that it would continue to work for future versions of jqGrid. If anyone has any suggestions for better (less fragile) ways to solve this problem, I'm all ears. :)

这篇关于自动取消jqGrid请求的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆