1

Background: When user clicks a button its class is toggled between class1 and class2 and this data is submitted via AJAX. To confirm this data is saved, server responds with js (updates button HTML).

The Problem: if a user hits the button faster than the server can respond (ie hits the button quickly), the button will toggle back and forth once the server responses actually arrive:

  1. User hits button, changes to class2 via js (AJAX submitted)
  2. User hits button, changes to class1 via js (AJAX submitted)
  3. Server responds to first AJAX request, and refreshes html to class2
  4. Server responds to second AJAX request, and refreshes html to class1

How could the ajax request be cancelled, if a new one is made?

$('.button').click(function() {
    $('this').toggleClass('class1 class2')
    // submit ajax request
    $.ajax({
        url: '/update_link'
    })
});
Jeremy Lynch
  • 6,780
  • 3
  • 52
  • 63
  • 1
    Wouldn't it be a better idea to put a function on the button that makes it inactive for a few seconds after clicking? – Sander Aug 21 '16 at 14:03
  • Simply disable toggling up until the async function returns a response or timeouts and returns an error. – Redu Aug 21 '16 at 14:23
  • http://stackoverflow.com/questions/446594/abort-ajax-requests-using-jquery – epascarello Aug 21 '16 at 16:44

2 Answers2

8

EDITED

Ajax call can be aborted by abort method used on ajax request object, but even usage this method not give as 100% certainty that server side not handled our request. So my proposition is to block user interface, not abort ajax calls.

Some more information about abort - How to cancel/abort jQuery AJAX request?

EXAMPLE BLOCK UI:

So to block many ajax calls we need some variable to save current ajax state, and set it to true in begging ( ajax enabled ), when ajax is called set it to false, when ajax return in response set it again to true. And most important check this variable when user clicks, if variable is false, then no other ajax can be called and stop execution.

var canSendAjax=true;//our state variable

$('.button').click(function() {

    if (!canSendAjax)
    return; //ajax is sending block execution

    $('this').toggleClass('class1 class2')
    // submit ajax request

    //here ajax starts so set state to false
    canSendAjax=false;

    //extended to solution loading info
    //save button current text label in variable
    var label=$(this).text();
    //set loading on button for ui friendly
    $(this).text("Loading...");

    $.ajax({
        url: '/update_link'
    }).done(function() {

       //here after ajax
       canSendAjax=true; //we enable button click again
       $(this).text(label);//set previous button label

    });

});

EXAMPLE WITH USAGE OF ABORT:

var ajax=null; //our ajax call instance

$('.button').click(function() {


    if (ajax!=null){

        ajax.abort();

        ajax=ajax=$.ajax({
          url: '/update_link'
        });
    }


});
Community
  • 1
  • 1
Maciej Sikora
  • 19,374
  • 4
  • 49
  • 50
0

Why don't you simply disable the button and toggle the class once the request is done?

$('.button').click(function() {
    $this = $(this);
    $this.prop('disabled', true);
    // submit ajax request
    $.ajax({
        url: '/update_link',
        success: function() {
            $.toggleClass('class1 class2');
            $this.prop('disabled', false);
        }
    })
});

(click event triggering is not working if the input is disabled)

Hulothe
  • 744
  • 1
  • 5
  • 17