У меня есть запрос AJAX, который будет выполняться каждые 5 секунд. Но проблема перед запросом AJAX, если предыдущий запрос не завершен, я должен прервать этот запрос и сделать новый запрос.
Мой код выглядит примерно так: как решить эту проблему?
$(document).ready(
var fn = function(){
$.ajax({
url: 'ajax/progress.ftl',
success: function(data) {
//do something
}
});
};
var interval = setInterval(fn, 500);
);
Метод jQuery ajax возвращает объект XMLHttpRequest. Вы можете использовать этот объект для отмены запроса.
XMLHttpRequest имеет метод abort, который отменяет запрос, но если запрос уже отправлен на сервер, тогда сервер будет обрабатывать запрос даже если мы отменим запрос, но клиент не будет ждать/обрабатывать ответ.
Объект xhr также содержит readyState, который содержит состояние запроса (UNSENT-0, OPENED-1, HEADERS_RECEIVED-2, LOADING-3 и Совершено-4). мы можем использовать это, чтобы проверить, был ли предыдущий запрос завершен.
$(document).ready(
var xhr;
var fn = function(){
if(xhr && xhr.readyState != 4){
xhr.abort();
}
xhr = $.ajax({
url: 'ajax/progress.ftl',
success: function(data) {
//do something
}
});
};
var interval = setInterval(fn, 500);
);
readystate
выше и readyState
ниже, символ s
заглавными в jQuery 1.5
Просто используйте ajax.abort(), например, вы можете прервать любой ожидающий запрос ajax перед отправкой другого, подобного этому
//check for existing ajax request
if(ajax){
ajax.abort();
}
//then you make another ajax request
$.ajax(
//your code here
);
Я знаю, что это может быть немного поздно, но у меня возникают аналогичные проблемы, когда вызов метода прерывания действительно не прервал запрос. вместо этого браузер все еще ожидал ответа, который он никогда не использует. этот код разрешил эту проблему.
try {
xhr.onreadystatechange = null;
xhr.abort();
} catch (e) {}
Зачем вам отменять запрос?
Если каждый запрос занимает более пяти секунд, что произойдет?
Вы не должны прерывать запрос, если параметр, передаваемый с запросом, не изменяется. например: - запрос на получение данных уведомления. В таких ситуациях приятным подходом является то, что задать новый запрос только после завершения предыдущего запроса Ajax.
$(document).ready(
var fn = function(){
$.ajax({
url: 'ajax/progress.ftl',
success: function(data) {
//do something
},
complete: function(){setTimeout(fn, 500);}
});
};
var interval = setTimeout(fn, 500);
);
Вы можете использовать jquery-validate.js. Ниже приведен фрагмент кода из jquery-validate.js.
// ajax mode: abort
// usage: $.ajax({ mode: "abort"[, port: "uniqueport"]});
// if mode:"abort" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort()
var pendingRequests = {},
ajax;
// Use a prefilter if available (1.5+)
if ( $.ajaxPrefilter ) {
$.ajaxPrefilter(function( settings, _, xhr ) {
var port = settings.port;
if ( settings.mode === "abort" ) {
if ( pendingRequests[port] ) {
pendingRequests[port].abort();
}
pendingRequests[port] = xhr;
}
});
} else {
// Proxy ajax
ajax = $.ajax;
$.ajax = function( settings ) {
var mode = ( "mode" in settings ? settings : $.ajaxSettings ).mode,
port = ( "port" in settings ? settings : $.ajaxSettings ).port;
if ( mode === "abort" ) {
if ( pendingRequests[port] ) {
pendingRequests[port].abort();
}
pendingRequests[port] = ajax.apply(this, arguments);
return pendingRequests[port];
}
return ajax.apply(this, arguments);
};
}
Чтобы вам просто нужно было установить параметр прервать, когда вы делаете запрос ajax.
Ссылка: /jquery.validate.js
JQuery: Используйте это как отправную точку - как вдохновение. Я решил это так: (это не идеальное решение, оно просто отменяет последний экземпляр и является кодом WIP)
var singleAjax = function singleAjax_constructor(url, params) {
// remember last jQuery get request
if (this.lastInstance) {
this.lastInstance.abort(); // triggers .always() and .fail()
this.lastInstance = false;
}
// how to use Deferred : http://api.jquery.com/category/deferred-object/
var $def = new $.Deferred();
// pass the deferrer request handlers into the get response handlers
this.lastInstance = $.get(url, params)
.fail($def.reject) // triggers .always() and .fail()
.success($def.resolve); // triggers .always() and .done()
// return the deferrer "control object", the promise object
return $def.promise();
}
// initiate first call
singleAjax('/ajax.php', {a: 1, b: 2})
.always(function(a,b,c) {console && console.log(a,b,c);});
// second call kills first one
singleAjax('/ajax.php', {a: 1, b: 2})
.always(function(a,b,c) {console && console.log(a,b,c);});
// here you might use .always() .fail() .success() etc.
Когда вы делаете запрос на сервер, попросите его проверить, не проделан ли прогресс не null (или выборка данных). Если он извлекает данные, отмените предыдущий запрос и инициируйте новый.
var progress = null
function fn () {
if (progress) {
progress.abort();
}
progress = $.ajax('ajax/progress.ftl', {
success: function(data) {
//do something
progress = null;
}
});
}
Метод jQuery ajax возвращает объект XMLHttpRequest. Вы можете использовать этот объект для отмены запроса.
$(document).ready(
var xhr;
var fun = function(){
if(xhr && xhr.readyState != 4){
xhr.abort();
}
xhr = $.ajax({
url: 'ajax/progress.ftl',
success: function(data) {
//do something code here
}
});
};
var interval = setInterval(fun, 1000);
);
Я надеюсь, что этот ответ будет полезен для вас.
Вы также должны проверить наличие readyState 0. Так как при использовании xhr.abort() эта функция устанавливает readyState в 0 в этом объекте, а ваша проверка if всегда будет true - readyState!= 4
$(document).ready(
var xhr;
var fn = function(){
if(xhr && xhr.readyState != 4 && xhr.readyState != 0){
xhr.abort();
}
xhr = $.ajax({
url: 'ajax/progress.ftl',
success: function(data) {
//do something
}
});
};
var interval = setInterval(fn, 500);
);