0

I have a shopping cart where a user can add more items, change quantity of existing items, remove items and such. For each of these actions, I do an async AJAX call to the server in order to update the Order total.

What happens is that if the user adds an item (action 1), I do the async call, and then the user changes the quantity of another item (action 2), I would like the response of action 2 to show up. Since these calls are async, maybe the latest response that I get is the one from action 1, and therefore the order total is incorrect.

What pattern should I follow to not trigger the same AJAX call until the previous one has finished?

To clarify:

The AJAX requests that are happening are the same ones. Say I do this $.get('destination_url'). I just need to make sure that that I don't do the same request until the previous one is done/failed.

Hommer Smith
  • 26,772
  • 56
  • 167
  • 296
  • 1
    I think you may be looking for promise objects: see [`.promise()`](https://api.jquery.com/promise/). You may find it useful to look into the [`.done()`](https://api.jquery.com/deferred.done/), [`.fail()`](https://api.jquery.com/deferred.fail/) and [`.always()`](https://api.jquery.com/deferred.always/) methods. – War10ck Jun 01 '15 at 15:31
  • I suggest you take a look at the following SO article. jAndy's answer is what you are looking for. [Queue ajax requests using jQuery.queue()](http://stackoverflow.com/questions/4785724/queue-ajax-requests-using-jquery-queue) – BobbyDazzler Jun 01 '15 at 15:39
  • You may want to block other options when tasks related to the selected option are in progress, such as showing a spinner or disabling other options etc. – lshettyl Jun 01 '15 at 15:47

4 Answers4

1

Updated:

function AjaxCall1()
{
    return $.ajax({
        type: "POST",
        url: webMethod,
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        data: parameters,
        success: function (data, st) {
        }   
}

$(document).ready(function () {
    $.when(AjaxCall1()).done(function(){
        AjaxCall1(); //call same ajax call again once the first one is called 
    })
});
imGreg
  • 900
  • 9
  • 24
  • This would not help. The ajax calls are the same. I just need to make sure that one doesn't happen until the first one has happened. – Hommer Smith Jun 01 '15 at 16:37
  • @HommerSmith I updated my answer. Unless, are they are being triggered from 2 different places? – imGreg Jun 01 '15 at 16:45
0

I suggest that you trigger consecutive ajax requests after the done() for the current ajax request is called:

$.ajax(options).done(function (data) {
    // your logic
    $.ajax(newOptions);
});
Konstantin Dinev
  • 34,219
  • 14
  • 75
  • 100
  • I don't see how this would allow OP to "queue" his requests. It's all fair and well doing the new AJAX in the .done() callback, but it will not trigger his subsequent requests if they are done in rapid succession. – BobbyDazzler Jun 01 '15 at 15:33
0

jQuery.active returns an integer which is the number of active ajax requests open currently.

So you could do a check before you make the ajax call,

function checkAndCallAjax() {
  if(jQuery.active == 0) { doAjax() }
}

and then add and ajaxStop handlers to call checkAndCallAjax you can ensure you have no parallel order requests. AjaxStop will let you know when an ajax call ends.

cowboybebop
  • 2,225
  • 3
  • 21
  • 31
0

As I said in my comment, one of the options would be to programmatically activate/deactivate controls when any of the actions is active. When the selected action is complete (ajax done, do stuff with ajax data etc.) activate the controls, so that user would perform the next action etc. Below is the code that demonstrates what I mean.

$(function() {

    $("#actions").on("click", ".update", function() {
        var $this = $(this);
        var label = $this.text();
        $this.siblings().prop("disabled", true);
        $this.text("Please wait...");
        //Ajax call
        $.ajax({
            method: "POST", // or whatever fits
            url: "/echo/html/", // your url
            data: { method: "methodName" } // whatever data
        }).done(function( data ) {
            //do stuff with returned data
            //Enable the controls
            $this.siblings().prop("disabled", false);
            $this.text(label);
        }).fail(function() {
            //Handler error related stuff
            alert( "There was an error!" );
            //Enable the controls
            $this.siblings().prop("disabled", false);
        });
    });
});

Sample HTML:

<div id="actions">
    <button class="update add">+1</button>
    <button class="update subtract">-1</button>
    <button class="update delete">Delete</button>
</div>

=Working Demo=

Hope that helps.

lshettyl
  • 8,166
  • 4
  • 25
  • 31