自动取消jqGrid请求

问题描述:

我认为这个用户提出了我所问的同一个问题,但推动他的问题的原因是不同的,所以他接受了不同的解决方案。我需要做什么,他最初问:自动取消jqGrid请求

Automatically cancelling jqgrid request

我的jqGrid有一个搜索工具栏(即出现下面的列标题,但上面的数据输入字段)。大多数列都有下拉列表(stype = select),列出了该列的可用过滤选项,顶部有一个“全部”选项。用填充我的jqGrid的JSON数据响应的服务器端代码非常复杂,因此速度有点慢,特别是当过滤条件没有太多的时候。这意味着如果用户选择“全部”,则可能需要几秒钟才能显示结果。这本身就很好,但如果用户在响应返回之前做出另一个筛选器选择,则网格不会取消现有的请求,也不会提交新的请求,因此在之后的某个点处,用户进行第二次选择,网格会更新以显示第一个选择的响应。此外,网格自动更新,当你选择过滤器时,为了让它显示你想要的数据,你必须改变你的选择,等待它加载,然后再改回来。

这里是我试过到目前为止:

$(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都显示相同的行为。

如何取消正在进行的请求并根据用户最近的选择继续进行搜索?这是jqGrid中的错误吗?我最初在版本4.2上遇到过这个问题;我刚刚升级到4.4.4,这种行为没有任何变化。

看着jqGrid代码,我看到的行为似乎是不可避免的,无需更改jqGrid代码本身。 jqGrid在每个请求的开始处设置一个标志(ts.grid.hDiv.loading),并在最后清除它;当设置此标志时,不会提交新的过滤标准,也不会触发事件。

我也考虑过修改我的JSON响应,以便它包含请求标准,然后编写一些JS代码来将响应与当前条件选择进行比较。如果它们不匹配,我会忽略该响应并且不将其呈现给网格。由于jqGrid甚至不提交第二组标准,该选项不在表格中(即使我能解决这个问题,我目前的方法似乎也是可取的)。

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

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()的末尾添加一个对这个函数的调用。

此代码显式清除ts.grid.hDiv。加载标志,这是不公布的jqGrid API的一部分,所以我认为这个解决方案相当脆弱;不能保证它会继续为未来版本的jqGrid工作。如果任何人有任何关于解决这个问题的更好(不那么脆弱)方法的建议,我全都听过。 :)

@JakeRobb谢谢你的想法!我冒昧地创建了一个可以普遍使用的函数,而不禁用原始jqGrid的任何功能。

测试上的jqGrid 5.2.1版

jqGrid的快速搜索

a.k.a自动如果一个新的过滤器由使用者施加取消旧的请求。

/** 
 
* Add the ability to rapidly search using the jqGrid Toolbar 
 
* 
 
* @param jqGridInstance string|object 
 
* 
 
* @author Kiril Reznik 
 
*/ 
 
var jqGridRapidSearch = function(jqGridInstance) { 
 
    var currentRequest = null, 
 
     abortRequest = function() { 
 
      if (currentRequest !== null) { 
 
       currentRequest.abort(); 
 
      } 
 
     }, 
 
     setRequest = function(xhr) { 
 
      abortRequest(); 
 
      currentRequest = xhr; 
 
     }, 
 
     clearRequest = function() { 
 
      abortRequest(); 
 
      currentRequest = null; 
 
     }, 
 
     $jqGrid = null; 
 
    if ($.type(jqGridInstance) === 'string') { 
 
     $jqGrid = $(jqGridInstance); 
 
    } else if ($.type(jqGridInstance) === 'object' && $.type(jqGridInstance.jquery) === 'string') { 
 
     $jqGrid = jqGridInstance; 
 
    } else { 
 
     throw 'jqGridRapidSearch requires a valid jqGrid instance parameter: Grid ID string or jQuery object.'; 
 
    } 
 
    $jqGrid.on('jqGridLoadBeforeSend', function(e, xhr, settings) { 
 
     setRequest(xhr); 
 
    }); 
 
    $jqGrid.on('jqGridLoadComplete', function(e, data) { 
 
     clearRequest(); 
 
    }); 
 
    $jqGrid.on('jqGridLoadError', function(e, xhr, status, error) { 
 
     clearRequest(); 
 
    }); 
 
    $jqGrid.on('jqGridToolbarBeforeSearch', function(e) { 
 
     clearRequest(); 
 
    }); 
 
};