Abortar solicitudes de Ajax usando jQuery

1914

¿Es posible que al usar jQuery, cancele / aborte una solicitud Ajax de la que aún no he recibido la respuesta?

2
  • 2
    Tal vez he entendido mal la pregunta, pero ¿no podrías simplemente usarla $.ajaxStop? Luke Madhanga 13/0913 a las 11:47
  • 17
    @LukeMadhanga; Creo que ajaxStopsolo detecta cuando se completan todas las solicitudes AJAX, no detiene una solicitud. En mi experiencia, se usaría así: $(document).ajaxStop(function(){alert("All done")}). Usar .abort()es la mejor opción. TheCarver 9/12/2013 a las 11:35
1811

La mayoría de los métodos jQuery Ajax devuelven un objeto XMLHttpRequest (o el equivalente), por lo que puede usar abort().

Ver la documentación:

var xhr = $.ajax({
    type: "POST",
    url: "some.php",
    data: "name=John&location=Boston",
    success: function(msg){
       alert( "Data Saved: " + msg );
    }
});

//kill the request
xhr.abort()

ACTUALIZACIÓN: A partir de jQuery 1.5, el objeto devuelto es un contenedor para el objeto XMLHttpRequest nativo llamado jqXHR. Este objeto parece exponer todas las propiedades y métodos nativos, por lo que el ejemplo anterior aún funciona. Consulte El objeto jqXHR (documentación de la API de jQuery).

ACTUALIZACIÓN 2: A partir de jQuery 3, el método ajax ahora devuelve una promesa con métodos adicionales (como abortar), por lo que el código anterior aún funciona, aunque el objeto que se devuelve ya no lo es xhr. Vea el blog 3.0 aquí .

ACTUALIZACIÓN 3 : xhr.abort()todavía funciona en jQuery 3.x. No asuma que la actualización 2 es correcta. Más información sobre el repositorio jQuery Github .

0
123

No puede recordar la solicitud, pero puede establecer un valor de tiempo de espera después del cual se ignorará la respuesta. Consulte esta página para conocer las opciones de jquery AJAX. Creo que se llamará a su devolución de llamada de error si se excede el período de tiempo de espera. Ya existe un tiempo de espera predeterminado en cada solicitud AJAX.

También puede utilizar el aborto () método en el objeto solicitud, pero, mientras que hará que el cliente deje de detectar el evento, se puede probablemente no va a detener el servidor de procesarlo.

80

Es una asynchronoussolicitud, lo que significa que una vez que se envía, está disponible.

En caso de que su servidor esté iniciando una operación muy costosa debido a la AJAXsolicitud, lo mejor que puede hacer es abrir su servidor para escuchar las solicitudes de cancelación y enviar una AJAXsolicitud por separado notificando al servidor que detenga lo que esté haciendo.

De lo contrario, simplemente ignore la AJAXrespuesta.

1
  • 53
    En este contexto, asincrónico simplemente significa que la solicitud no interrumpe el flujo del script. Los navegadores ahora tienen la capacidad de cancelar la solicitud prematuramente antes de que se complete la solicitud. ElephantHunter 10/04/12 a las 19:12
77

Guarde las llamadas que realice en una matriz, luego llame a xhr.abort () en cada una.

PRECAUCIÓN ENORME: Puede cancelar una solicitud, pero eso es solo del lado del cliente. El lado del servidor aún podría estar procesando la solicitud. Si está utilizando algo como PHP o ASP con datos de sesión, los datos de la sesión se bloquean hasta que finaliza el ajax. Entonces, para permitir que el usuario continúe navegando por el sitio web, debe llamar a session_write_close (). Esto guarda la sesión y la desbloquea para que otras páginas que esperan continuar continúen. Sin esto, varias páginas pueden estar esperando a que se elimine el candado.

0
68

Es posible que las solicitudes AJAX no se completen en el orden en que se iniciaron. En lugar de abortar, puede optar por ignorar todas las respuestas AJAX excepto la más reciente:

  • Crea un contador
  • Incrementa el contador cuando inicias la solicitud AJAX
  • Utilice el valor actual del contador para "sellar" la solicitud
  • En la devolución de llamada exitosa, compare el sello con el contador para verificar si fue la solicitud más reciente

Esquema aproximado del código:

var xhrCount = 0;
function sendXHR() {
    // sequence number for the current invocation of function
    var seqNumber = ++xhrCount;
    $.post("/echo/json/", { delay: Math.floor(Math.random() * 5) }, function() {
        // this works because of the way closures work
        if (seqNumber === xhrCount) {
            console.log("Process the response");
        } else {
            console.log("Ignore the response");
        }
    });
}
sendXHR();
sendXHR();
sendXHR();
// AJAX requests complete in any order but only the last 
// one will trigger "Process the response" message

Demostración en jsFiddle

0
47

Solo tuvimos que solucionar este problema y probar tres enfoques diferentes.

  1. cancela la solicitud como lo sugiere @meouw
  2. ejecutar todas las solicitudes pero solo procesa el resultado del último envío
  3. evita nuevas solicitudes siempre que haya otra pendiente

var Ajax1 = {
  call: function() {
    if (typeof this.xhr !== 'undefined')
      this.xhr.abort();
    this.xhr = $.ajax({
      url: 'your/long/running/request/path',
      type: 'GET',
      success: function(data) {
        //process response
      }
    });
  }
};
var Ajax2 = {
  counter: 0,
  call: function() {
    var self = this,
      seq = ++this.counter;
    $.ajax({
      url: 'your/long/running/request/path',
      type: 'GET',
      success: function(data) {
        if (seq === self.counter) {
          //process response
        }
      }
    });
  }
};
var Ajax3 = {
  active: false,
  call: function() {
    if (this.active === false) {
      this.active = true;
      var self = this;
      $.ajax({
        url: 'your/long/running/request/path',
        type: 'GET',
        success: function(data) {
          //process response
        },
        complete: function() {
          self.active = false;
        }
      });
    }
  }
};
$(function() {
  $('#button').click(function(e) {
    Ajax3.call();
  });
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="button" type="button" value="click" />

En nuestro caso, decidimos utilizar el enfoque n. ° 3, ya que produce menos carga para el servidor. Pero no estoy 100% seguro de que jQuery garantice la llamada del método .complete (), esto podría producir una situación de punto muerto. En nuestras pruebas no pudimos reproducir tal situación.

43

Siempre es una buena práctica hacer algo como esto.

var $request;
if ($request != null){ 
    $request.abort();
    $request = null;
}

$request = $.ajax({
    type : "POST", //TODO: Must be changed to POST
    url : "yourfile.php",
    data : "data"
    }).done(function(msg) {
        alert(msg);
    });

Pero es mucho mejor si verifica una declaración if para verificar si la solicitud ajax es nula o no.

1
  • 3
    También verifico si ya se está ejecutando una solicitud, pero uso un booleano, ya que es más ligero. Zesty 29 de julio de 2015 a las 5:02
18

Simplemente llame a xhr. abort () ya sea un objeto jquery ajax o un objeto XMLHTTPRequest nativo.

ejemplo:

//jQuery ajax
$(document).ready(function(){
    var xhr = $.get('/server');
    setTimeout(function(){xhr.abort();}, 2000);
});

//native XMLHTTPRequest
var xhr = new XMLHttpRequest();
xhr.open('GET','/server',true);
xhr.send();
setTimeout(function(){xhr.abort();}, 2000);
0
15

Como han señalado muchas personas en el hilo, solo porque la solicitud se cancela en el lado del cliente, el servidor seguirá procesando la solicitud. Esto crea una carga innecesaria en el servidor porque está haciendo un trabajo que dejamos de escuchar en el front-end.

El problema que estaba tratando de resolver (que otros pueden encontrar también) es que cuando el usuario ingresó información en un campo de entrada, quería enviar una solicitud para un tipo de sensación de Google Instant.

Para evitar disparar solicitudes innecesarias y mantener la agilidad del front-end, hice lo siguiente:

var xhrQueue = [];
var xhrCount = 0;

$('#search_q').keyup(function(){

    xhrQueue.push(xhrCount);

    setTimeout(function(){

        xhrCount = ++xhrCount;

        if (xhrCount === xhrQueue.length) {
            // Fire Your XHR //
        }

    }, 150);

});

Básicamente, esto enviará una solicitud cada 150 ms (una variable que puede personalizar para sus propias necesidades). Si tiene problemas para comprender qué está sucediendo exactamente aquí, inicie sesión xhrCounty acceda xhrQueuea la consola justo antes del bloque if.

0
15

Puede abortar cualquier llamada ajax continua usando esto

<input id="searchbox" name="searchbox" type="text" />

<script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
<script type="text/javascript">
     var request = null;
        $('#searchbox').keyup(function () {
            var id = $(this).val();
            request = $.ajax({
                type: "POST", //TODO: Must be changed to POST
                url: "index.php",
                data: {'id':id},
                success: function () {
    
                },
                beforeSend: function () {
                    if (request !== null) {
                        request.abort();
                    }
                }
            });
        });
</script>
14

Estaba haciendo una solución de búsqueda en vivo y necesitaba cancelar las solicitudes pendientes que pueden haber demorado más que la solicitud más reciente / más actual.

En mi caso usé algo como esto:

//On document ready
var ajax_inprocess = false;

$(document).ajaxStart(function() {
ajax_inprocess = true;
});

$(document).ajaxStop(function() {
ajax_inprocess = false;
});

//Snippet from live search function
if (ajax_inprocess == true)
{
    request.abort();
}
//Call for new request 
0
12

Simplemente use ajax.abort () por ejemplo, podría abortar cualquier solicitud de ajax pendiente antes de enviar otra como esta

//check for existing ajax request
if(ajax){ 
 ajax.abort();
 }
//then you make another ajax request
$.ajax(
 //your code here
  );
0
11

no hay una forma confiable de hacerlo, y ni siquiera lo probaría, una vez que la solicitud esté en marcha; la única forma de reaccionar razonablemente es ignorar la respuesta.

en la mayoría de los casos, puede suceder en situaciones como: un usuario hace clic con demasiada frecuencia en un botón que activa muchos XHR consecutivos, aquí tiene muchas opciones, bloquear el botón hasta que se devuelva XHR o ni siquiera activar un nuevo XHR mientras otro está ejecutando sugerencias que el usuario se recueste, o descarte cualquier respuesta XHR pendiente que no sea la reciente.

8

El siguiente código muestra el inicio y el aborto de una solicitud Ajax:

function libAjax(){
  var req;
  function start(){

  req =    $.ajax({
              url: '1.php',
              success: function(data){
                console.log(data)
              }
            });

  }

  function stop(){
    req.abort();
  }

  return {start:start,stop:stop}
}

var obj = libAjax();

 $(".go").click(function(){


  obj.start();


 })



 $(".stop").click(function(){

  obj.stop();


 })
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="button" class="go" value="GO!" >
   <input type="button" class="stop" value="STOP!" >
1
  • 5
    Proporcione una explicación de cómo esto resuelve la pregunta. Esto ayudará al OP y a otros buscadores futuros. SnareChops 29 de enero de 2016 a las 0:48
6

Tuve el problema de la encuesta y una vez que se cerró la página, la encuesta continuó, por lo que, por mi causa, un usuario se perdería una actualización ya que se estaba estableciendo un valor de mysql para los siguientes 50 segundos después del cierre de la página, aunque eliminé la solicitud de ajax, calculado, usar $ _SESSION para configurar una var no se actualizará en la encuesta hasta que finalice y haya comenzado una nueva, así que lo que hice fue establecer un valor en mi base de datos como 0 = fuera de página, mientras estoy sondeo, consulto esa fila y devuelvo falso; cuando es 0, ya que la consulta en el sondeo obtendrá los valores actuales, obviamente ...

Espero que esto ayude

6

Si xhr.abort(); provoca la recarga de la página,

Entonces puede configurar onreadystatechangeantes de abortar para prevenir:

// ↓ prevent page reload by abort()
xhr.onreadystatechange = null;
// ↓ may cause page reload
xhr.abort();
5

Compartí una demostración que demuestra cómo cancelar una solicitud AJAX, si los datos no se devuelven desde el servidor dentro de un tiempo de espera predefinido.

HTML:

<div id="info"></div>

CÓDIGO JS:

var isDataReceived= false, waitTime= 1000; 
$(function() {
    // Ajax request sent.
     var xhr= $.ajax({
      url: 'http://api.joind.in/v2.1/talks/10889',
      data: {
         format: 'json'
      },     
      dataType: 'jsonp',
      success: function(data) {      
        isDataReceived= true;
        $('#info').text(data.talks[0].talk_title);        
      },
      type: 'GET'
   });
   // Cancel ajax request if data is not loaded within 1sec.
   setTimeout(function(){
     if(!isDataReceived)
     xhr.abort();     
   },waitTime);   
});
1
  • 1
    $.ajaxproporciona una timeoutopción para que no tenga que escribir la suya propia. Simplemente use ..., data: {...}, timeout: waitTime,.... Bram Vanroy 6 de julio de 2016 a las 19:54
1

Esta es mi implementación basada en muchas respuestas anteriores:

  var activeRequest = false; //global var
  var filters = {...};
  apply_filters(filters);

  //function triggering the ajax request
  function apply_filters(filters){
        //prepare data and other functionalities
        var data = {};
        //limit the ajax calls
        if (activeRequest === false){
          activeRequest = true;
        }else{
          //abort if another ajax call is pending
          $request.abort();
          //just to be sure the ajax didn't complete before and activeRequest it's already false
          activeRequest = true;        
        }

        $request = $.ajax({ 
          url : window.location.origin + '/your-url.php',
          data: data,
          type:'POST',
          beforeSend: function(){
            $('#ajax-loader-custom').show();
            $('#blur-on-loading').addClass('blur');
          },            
          success:function(data_filters){

              data_filters = $.parseJSON(data_filters);
              
              if( data_filters.posts ) {
                  $(document).find('#multiple-products ul.products li:last-child').after(data_filters.posts).fadeIn();
              }
              else{ 
                return;
              }
              $('#ajax-loader-custom').fadeOut();
          },
          complete: function() {
            activeRequest = false;
          }          
        }); 
  }