自动取消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();
});
};