2010-12-29 15 views
229

Tengo una solicitud de AJAX que se realizará cada 5 segundos. Pero el problema es antes de la solicitud de AJAX si no se completa la solicitud anterior. Tengo que cancelar esa solicitud y hacer una nueva solicitud.Cómo cancelar/abortar la solicitud jQuery AJAX?

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); 
); 
+10

posible duplicado de [. Matar peticiones Ajax utilizando javascript usando jquery] (http://stackoverflow.com/questions/446594/kill-ajax-requests-using-javascript-using-jquery) – karim79

+5

Su pregunta indica que la solicitud debe realizarse cada 5 segundos, pero el código usa 500 ms = 0.5 s. – geon

Respuesta

331

El método jquery ajax devuelve un objeto XMLHttpRequest. Puede usar este objeto para cancelar la solicitud.

El XMLHttpRequest tiene un método abort, que cancela la solicitud, pero si el pedido ya ha sido enviado al servidor entonces el servidor procesará la solicitud incluso si abortar la solicitud, pero el cliente no esperará a/manejar la respuesta.

El objeto xhr también contiene un 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); 
); 
+3

@rtpHarry Gracias por la actualización wrt jQuery 1.5 –

+59

@romkyns La diferencia es la propiedad 'readystate' anterior y' readyState' a continuación, el carácter 's' está en mayúscula en jQuery 1.5 –

+1

¡De hecho, gracias! –

3

¿Por qué debe abortar la solicitud?

Si cada solicitud lleva más de cinco segundos, ¿qué sucederá?

No debe cancelar 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 establecer 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); 

); 
+3

Esta es una mala idea. Al iniciar una nueva llamada, no desea que se dispare el evento completo de la llamada anterior. Puede obtener resultados muy extraños con este enfoque. – Webberig

+0

@Webberig ¡Gracias! actualizó la respuesta con la situación. –

0

Cuando realiza una solicitud a un servidor, haga que verifique si un progreso no es nulo (o busca esos datos) primero. Si está buscando datos, anule 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; 
     } 
    }); 
} 
0

jQuery: utilizar esto como un punto de partida - como fuente de inspiración. Lo resuelto de esta manera: (esto no es una solución perfecta, sólo se cancela la última instancia y es de 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. 
-7

También debe comprobar para readyState 0. Debido a que cuando se utiliza xhr.abort () esta función establece readyState a 0 en este objeto, y su caso cheque será siempre verdad - 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); 
); 
+2

¿Copió y pegó la respuesta de Arun? Porque la probabilidad de que dos bloques de código sean exactamente iguales, espaciados y todos ... –

+0

@ user2700923 Su publicación no es exactamente la misma. Su punto es que también deberíamos verificar readyState 0. Sin embargo, esto habría sido más apropiado como un comentario a la respuesta de Arun. – Stefan

5

sé que esto puede ser un poco tarde pero experimentar problemas similares en los que una llamada al método de aborto aún no ha realmente 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) {} 
+0

Tuve el mismo problema y esto funcionó. –

0

Puede 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); 
    }; 
} 

Así que simplemente sólo tiene que establecer el parámetro de modo de a abortar cuando presenta solicitud de ajax.

Ref: https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.14.0/jquery.validate.js

Cuestiones relacionadas