简体   繁体   中英

How to stop all active or pending ajax requests?

In my rails app, using jquery slider. In stop event of slider, there is ajax request. If user continuously sliding slider there are too many pending ajax requests and my system get hang. I have used:

1:

function slide_stop(event, ui){
    $.xhrPool = [];
    $.xhrPool.abortAll = function() {
       $(this).each(function(idx, jqXHR) {
          jqXHR.abort();
       });
       $.xhrPool.length = 0
    };

    $.ajaxSetup({
      beforeSend: function(jqXHR) {
          $.xhrPool.push(jqXHR);
      },
      complete: function(jqXHR) {
         var index = $.xhrPool.indexOf(jqXHR);
         if (index > -1) {
            $.xhrPool.splice(index, 1);
         }
      }
   });
   $.xhrPool.abortAll();
   $('span#imgLoader').html('<img src="/assets/ajax-loader.gif">');
   $.ajax({
     type: 'get',
     dataType: 'json',
     url: 'some_url',
     data: { is_ajax: true }
   }).done(function(response){       
    $('span#imgLoader').empty();
   });
 }

 Initialize slider,
     $elt.slider({
        min:0,
        max:100,
        value:50,
        slide: slide_range,
        stop: slide_stop
    }).each(function(){
     add_range_label($range_elt);
    });

All ajax requests get stopped/in not modified state. But last request takes too long time to complete. No result again same hanging state.

2:

var request = $.ajax(
{
    type: 'POST',
    url: 'someurl',
    success: function(result){}
});

then,

request.abort();

Not working. Too many requests are still in pending state. I don't know what is wrong with it.

I tried using 'jquery-throttle-debounce'. Included file 'jquery.ba-throttle-debounce.min.js' Applied jQuery.debounce to stop event for slider.

$("#slider").on( "slidestop", $.debounce( 240, slide_stop ) );

I tried by reducing time delay. But no expected result. Same case as above.

Try to throttle those requests, so many request to server can cause a performance issue on your server side, because remember that each ajax call is an apache (or whatever your webserver is) request, which costs memory and cpu. And remember that excesive requests can cause a DDoS.

Remember that as an user, i can start playing with the slider so much as i like, causing a ton of requests.

You should add something like:

var requests = [];
var lastCall = (+new Date()); // parenthesis just in case of minify
var timeDiff = 1000;

function sliderStopCallback() { // this will be called each time the slider stop sliding
     if(timeDiff < 400) {
         return;
     }

     abortAll();

     requests.push( $.ajax({
                             type: 'POST',
                             url: 'someurl',
                             success: function(result){}
               }) );
}

function sliderStartCallback() {  // this will be call each time the user start to slide
     timeDiff = (+new Date()) - lastCall;
     lastCall = (+new Date());
}

function abortAll() {
     var l = requests.length;
     while(l--) {
         requests[l].abort && requests[l].abort();  // the if is for the first case mostly, where array is still empty, so no abort method exists.
     }
}

That way, each request will be sent at least on 400 milliseconds, preventing calls every 2 seconds.

This should work, but please notice that i havent tested it, so if you're going to try it please remember that it is a general idea, not a precise solution.

Good luck.

You can use a plugin such as http://archive.plugins.jquery.com/project/AjaxManager .

Also, as Javis mentioned you are best off to also incorporate a delay before sending the response so that you don't needlessly overload your server with requests. Instead of using time differences or arrays I would just keep a reference to the last ajax request created. You would abort that request each time a new one is made.

// just putting these here for example, you would want to associate them with each instance of your slider control. 
var timeout, last_request; 

function slide_stop(event, ui){

   $('span#imgLoader').html('<img src="/assets/ajax-loader.gif">');
   // clear the timeout so a previous request won't be sent
   clearTimeout(timeout) 
   // set the request to be sent in .5 seconds
   timeout = setTimeout(send_request, 500); 
 }

function send_request(){
   // abort the last request if there is one
   if(last_request){
     last_request.abort();
   }
   last_request = $.ajax({
     type: 'get',
     dataType: 'json',
     url: 'some_url',
     data: { is_ajax: true }
   }).done(function(response){       
    $('span#imgLoader').empty();
    // set the last request to null so that you dont abort a completed request 
    //(this might not be necessary)
    last_request = null; 
   });
}

As said in comments, it's best to not send the request until the slideStop event. This way requests are not sent every time the value is changed, and thus server load is much less of an issue.

function ajaxrequest(){
    $.ajax(....);
}

$("#slider").on("slideStop", function() {

    ajaxrequest();

});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM