Javascript 自动取消jqGrid请求
我想这个用户问的问题和我问的相同,但提出他的问题的原因不同,所以他接受了不同的解决方案。我需要做他最初要求的事情: 我的jqGrid有一个搜索工具栏(显示在列标题下方但在数据上方的输入字段)。大多数列都有下拉列表(stype=select),其中列出了该列的可用筛选选项,顶部有一个“All”选项。使用填充jqGrid的JSON数据进行响应的服务器端代码非常复杂,因此有点慢,尤其是在没有太多过滤条件的情况下。这意味着,如果用户选择“全部”,可能需要几秒钟才能显示任何结果。这本身没有问题,但如果用户在响应返回之前选择了另一个过滤器,网格不会取消现有请求,也不会提交新请求,因此在用户进行第二次选择后的某个时间点,网格会更新以显示第一次选择的响应。此外,当您更改过滤器选择时,网格会自动更新,因此为了让它显示您想要的数据,您必须将您的选择更改为其他内容,等待加载,然后再将其更改回来 以下是我迄今为止所尝试的:Javascript 自动取消jqGrid请求,javascript,ajax,jqgrid,xmlhttprequest,Javascript,Ajax,Jqgrid,Xmlhttprequest,我想这个用户问的问题和我问的相同,但提出他的问题的原因不同,所以他接受了不同的解决方案。我需要做他最初要求的事情: 我的jqGrid有一个搜索工具栏(显示在列标题下方但在数据上方的输入字段)。大多数列都有下拉列表(stype=select),其中列出了该列的可用筛选选项,顶部有一个“All”选项。使用填充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事件实际上不会触发。我尝试了事件文档页面()中的其他事件:beforeRequest和jqGridToolbarBeforeSearch都表现出相同的行为
如何中止飞行中的请求并根据用户最近的选择继续搜索?这是jqGrid中的一个bug吗?我最初在版本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.GID.HDIV.Load标志,这不是发布的JQGrand API的一部分,所以我认为这个解决方案相当脆弱;不能保证它在jqGrid的未来版本中会继续工作。如果有人对解决这个问题的更好(不那么脆弱)方法有任何建议,我洗耳恭听。:) @JakeRobb谢谢你的主意!我已经自由地创建了一个可以普遍使用的函数,而无需禁用原始jqGrid的任何功能 在jqGrid版本5.2.1上测试 jqGrid快速搜索 a、 k.a.如果用户应用了新筛选器,则自动取消旧请求
/**
*添加使用jqGrid工具栏快速搜索的功能
*
*@param jqGridInstance字符串|对象
*
*@作者基里尔·雷兹尼克
*/
var jqGridRapidSearch=函数(jqGridInstance){
var currentRequest=null,
abortRequest=函数(){
如果(currentRequest!==null){
currentRequest.abort();
}
},
setRequest=函数(xhr){
中止任务();
currentRequest=xhr;
},
clearRequest=函数(){
中止任务();
currentRequest=null;
},
$jqGrid=null;
if($.type(jqGridInstance)=='string'){
$jqGrid=$(jqGridInstance);
}else if($.type(jqGridInstance)=='object'&&&$.type(jqGridInstance.jquery)=='string'){
$jqGrid=jqGridInstance;
}否则{
抛出“jqGridRapidSearch需要有效的jqGrid实例参数:网格ID字符串或jQuery对象”;
}
$jqGrid.on('jqGridLoadBeforeSend',函数(e、xhr、设置){
设置请求(xhr);
});
$jqGrid.on('jqGridLoadComplete',函数(e,数据){
clearRequest();
});
$jqGrid.on('jqGridLoadError',函数(e、xhr、状态、错误){
clearRequest();
});
$jqGrid.on('jqGridToolbarBeforeSearch',函数(e){
clearRequest();
});
};
Hi@Aternus,我正在使用jqgrid 4.3.1版本,我检查了4.3.1 jqgrid不支持事件触发器处理程序,我们可以使用其他选项吗