我有以下代码用于自动保存,但我同时遇到大量Ajax请求,我想等待Ajax请求直到第一个Ajax请求未完成
window.submitting = false;
$('form#AddForm').submit(function() {
window.submitting = true;
});
var timeoutId;
$('form input, form textarea, form select').bind('input propertychange change', function() {
console.log('Change');
if (window.submitting)
return false;
clearTimeout(timeoutId);
timeoutId = setTimeout(function() {
// Runs 5 second (5000 ms)
autoSave();
}, 5000);
});
function autoSave() {
$.ajax({
type: "POST",
data: $('form#AddForm').serialize() + '&autosave=true',
beforeSend: function(xhr) {
// Let them know we are saving
console.log('Saving........');
},
success: function(data) {
var jqObj = jQuery(data); // Ajax call here.
var ProductId = jqObj.find("#ProductId").val();
var url = $(location).attr('href');
var split = url.split("add");
if (ProductId) {
history.pushState({}, null, split[0] + "add/" + ProductId);
$('#ProductId').val(ProductId);
$('form#AddForm').attr('action', '/dataproducts/add/' + ProductId);
}
},
});
}
答案 0 :(得分:3)
看起来我已经抓住了你的问题。如果用户在表单元素上触发了很少的更改事件,则会创建新的ajax请求,但不应该在上一个处理过程中。
我猜您可以在发送ajax之前使用下一种方法:取消绑定侦听器,然后在完成ajax时将它们绑定。
关于绑定/解除绑定,有一个很好的答案:Best way to remove an event handler in jQuery?
所以基本上你必须进行litle重构并添加几行代码:
window.submitting = false;
$('form#ProductAddForm').submit(function() {
window.submitting = true;
});
var timeoutId;
var saveHandler = function() {
console.log('Change');
if (window.submitting)
return false;
clearTimeout(timeoutId);
timeoutId = setTimeout(function() {
// Runs 5 second (5000 ms)
autoSave();
}, 5000);
};
$('form input, form textarea, form select').bind('input propertychange change', saveHandler);
function autoSave() {
// unbind events
$('form input, form textarea, form select').unbind('input propertychange change')
$.ajax({
type: "POST",
data: $('form#ProductAddForm').serialize() + '&autosave=true',
beforeSend: function(xhr) {
// Let them know we are saving
console.log('Saving........');
},
success: function(data) {
var jqObj = jQuery(data); // Ajax call here.
var ProductId = jqObj.find("#ProductId").val();
var url = $(location).attr('href');
var split = url.split("add");
if (ProductId) {
history.pushState({}, null, split[0] + "add/" + ProductId);
$('#ProductId').val(ProductId);
$('form#ProductAddForm').attr('action', '/account/products/add/' + ProductId);
}
// bind events back
$('form input, form textarea, form select').bind('input propertychange change', saveHandler);
},
error: function{
// bind events back even if reqeust fail
$('form input, form textarea, form select').bind('input propertychange change', saveHandler);
}
});
}
注意 jqXHR.success
和jqXHR.error
已弃用,有关详细信息,请参阅$.ajax。我还添加了error
方法,因为如果ajax失败,你不能错过绑定侦听器......
答案 1 :(得分:0)
我可能误解了这个问题,但我读到了这样的问题:
我不希望同时运行多个ajax请求。但 请求完成后,我想运行下一个。
您可以使用ajaxManager,如jAndy所建议的那样:Queue ajax requests using jQuery.queue()
var ajaxManager = (function() {
var requests = [];
return {
addReq: function(opt) {
requests.push(opt);
},
removeReq: function(opt) {
if( $.inArray(opt, requests) > -1 )
requests.splice($.inArray(opt, requests), 1);
},
run: function() {
var self = this,
oriSuc;
if( requests.length ) {
oriSuc = requests[0].complete;
requests[0].complete = function() {
if( typeof(oriSuc) === 'function' ) oriSuc();
requests.shift();
self.run.apply(self, []);
};
$.ajax(requests[0]);
} else {
self.tid = setTimeout(function() {
self.run.apply(self, []);
}, 1000);
}
},
stop: function() {
requests = [];
clearTimeout(this.tid);
}
};
}());
并在您的代码中使用它:
ajaxManager.run();
function autoSave() {
ajaxManager.addReq({
type: "POST",
data: $('form#ProductAddForm').serialize() + '&autosave=true',
beforeSend: function(xhr) {
// Let them know we are saving
console.log('Saving........');
},
success: function(data) {
var jqObj = jQuery(data); // Ajax call here.
var ProductId = jqObj.find("#ProductId").val();
var url = $(location).attr('href');
var split = url.split("add");
if (ProductId) {
history.pushState({}, null, split[0] + "add/" + ProductId);
$('#ProductId').val(ProductId);
$('form#ProductAddForm').attr('action', '/account/products/add/' + ProductId);
}
},
});
}
这样您就可以对不同的请求进行排队。但是,通过代码,您似乎总是发送整个表单。那么,如果下一个请求会发布更准确的值,为什么第一个请求会完成呢?显然有理由说你可能想发布每一个变化。但如果没有,你可以取消之前的请求并发送另一个请求。
var xhr;
function autoSave() {
if(xhr){
//TODO: Check if there is a current call.
// abort call.
xhr.abort();
}
xhr = $.ajax({
type: "POST",
data: $('form#ProductAddForm').serialize() + '&autosave=true',
beforeSend: function(xhr) {
// Let them know we are saving
console.log('Saving........');
},
success: function(data) {
var jqObj = jQuery(data); // Ajax call here.
var ProductId = jqObj.find("#ProductId").val();
var url = $(location).attr('href');
var split = url.split("add");
if (ProductId) {
history.pushState({}, null, split[0] + "add/" + ProductId);
$('#ProductId').val(ProductId);
$('form#ProductAddForm').attr('action', '/account/products/add/' + ProductId);
}
},
});
}