peticion - ¿Cómo cancelar/abortar la solicitud de jQuery AJAX?
jquery ajax abort (8)
Tengo una solicitud de AJAX que se hará cada 5 segundos. Pero el problema es antes de la solicitud AJAX si la solicitud anterior no está completa. Tengo que abortar esa solicitud y hacer una nueva solicitud.
Mi código es algo como esto, ¿cómo resolver este problema?
$(document).ready(
var fn = function(){
$.ajax({
url: ''ajax/progress.ftl'',
success: function(data) {
//do something
}
});
};
var interval = setInterval(fn, 500);
);
Crea una función para llamar a tu API. Dentro de esta función, definimos la solicitud callApiRequest = $.get(...
- aunque esta es una definición de una variable, la solicitud se llama inmediatamente, pero ahora tenemos la solicitud definida como una variable. Antes de llamar la solicitud, verifique si nuestra variable está definida como typeof(callApiRequest) != ''undefined''
y también si está pendiente de suggestCategoryRequest.state() == ''pending''
- si ambas son verdaderas, .abort()
la solicitud que evitará la devolución de llamada exitosa de correr.
// We need to wrap the call in a function
callApi = function () {
//check if request is defined, and status pending
if (typeof(callApiRequest) != ''undefined''
&& suggestCategoryRequest.state() == ''pending'') {
//abort request
callApiRequest.abort()
}
//define and make request
callApiRequest = $.get("https://example.com", function (data) {
data = JSON.parse(data); //optional (for JSON data format)
//success callback
});
}
Es posible que su servidor / API no admita el aborto de la solicitud (¿qué sucede si la API ya ejecutó algún código?), Pero la devolución de llamada de javascript no se activará. Esto es útil cuando, por ejemplo, está proporcionando sugerencias de entrada a un usuario, como la entrada de hashtags.
Puede ampliar aún más esta función agregando una definición de devolución de llamada de error, lo que debería suceder si se cancela la solicitud.
El caso de uso común para este fragmento sería una entrada de texto que se dispara en el evento de keypress
de keypress
. Puede usar un tiempo de espera para evitar enviar (algunas de) solicitudes que tendrá que cancelar .abort()
.
Cuando realice una solicitud a un servidor, haga que verifique si el progreso no es nulo (o está recuperando esos datos) primero. Si está recuperando datos, aborta la solicitud anterior e inicie la nueva.
var progress = null
function fn () {
if (progress) {
progress.abort();
}
progress = $.ajax(''ajax/progress.ftl'', {
success: function(data) {
//do something
progress = null;
}
});
}
El método jquery ajax devuelve un objeto XMLHttpRequest . Puede utilizar este objeto para cancelar la solicitud.
El XMLHttpRequest tiene un método de cancelación, que cancela la solicitud, pero si la solicitud ya se ha enviado al servidor, el servidor procesará la solicitud incluso si abortamos la solicitud pero el cliente no esperará / manejará la respuesta.
El objeto xhr también contiene un estado readyState que contiene el estado de la solicitud (UNSENT-0, OPENED-1, HEADERS_RECEIVED-2, LOADING-3 y DONE-4). Podemos usar esto para verificar si la solicitud anterior se completó.
$(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);
);
Puedes usar jquery-validate.js. El siguiente es el fragmento de código de 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);
};
}
De modo que solo necesita configurar el modo de parámetro para abortar cuando realice una solicitud ajax.
Ref: https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.14.0/jquery.validate.js
Sé que esto puede ser un poco tarde, pero tengo problemas similares en los que llamar al método abort no abortó la solicitud. en cambio, el navegador todavía estaba esperando una respuesta que nunca usa. este código resolvió ese problema.
try {
xhr.onreadystatechange = null;
xhr.abort();
} catch (e) {}
También debe verificar readyState 0. Debido a que cuando usa xhr.abort (), esta función establece readyState en 0 en este objeto, y su verificación if siempre será verdadera - 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);
);
jQuery: Usa esto como punto de partida, como inspiración. Lo resolví así: (esta no es una solución perfecta, simplemente aborta la última instancia y es un código WIP)
var singleAjax = function singleAjax_constructor(url, params) {
// remember last jQuery''s 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''s 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''s "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.
¿Por qué debería abortar la solicitud?
Si cada solicitud toma más de cinco segundos, ¿qué pasará?
No debe abortar la solicitud si el parámetro que pasa con la solicitud no está cambiando. por ejemplo: - la solicitud es para recuperar los datos de notificación. En tales situaciones, el buen enfoque es que establece una nueva solicitud solo después de completar la solicitud Ajax anterior.
$(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);
);