Ad

Callback When AJAX Calls Are Done Using JQuery When

- 1 answer

I am having trouble making the callback work correctly. Here is what I am trying to achieve: I have 2 items that I want to add to cart so I make 2 asynchronous POST requests. Once those two POST requests are complete, then I want to update the partial view of the cart. The issue is that it seems like only 1 item gets added to cart. When I debug it, then 2 of the items gets added. Any suggestion or help would be great. Thanks in advance!

here is my code:

var cart = []

function AddToCart(input) {
  return $.ajax({
    method: 'POST',
    url: '/cart/add.js',
    data: input,
    dataType: 'json'
  })
  .done(function(data) {
    return data;
  });
}  

$("#addToCart").click(function() {
  $('#capsContainer input:checked').each(function() {
    var cartItem = {
      id: $(this).val(),
      quantity: 1
    }

    cart.push(cartItem);
  });

  var test1 = AddToCart(cart[0]);
  var test2 = AddToCart(cart[1]);

  $.when.apply(test1, test2).done(function() {
        $.getJSON('/cart.js', function(data) {
        $('.cart-item-count').text(data.item_count);
        $('.cart-item-price').html(formatMoney(data.total_price));      
        ShowCart();
    });
  })
});
Ad

Answer

Part of the issue is that your using ajax requests which could occur either before or after the code happens to handle those executions. Since they are async, its possible that they could fire/return before any other code runs on the page depending on how your browser's Javascript parser decides to execute the code. Rather than attempting to use Callbacks on asynchronous ajax requests, you can control the entire interaction by using a small 600 byte library called ajaxq.js

ajaxq.js essentially works just like jQuery's $.post() method, only you can also specify multiple queues by name to execute asyncronously, and attach a callback to them or whatever.

Here's a quick example of how you could setup your Ajax Cart Preview using this library.

/* queue up an AJAX request */
$.postq("set_data", "add_items.php", {"itemID": someItemID, "customerID": customerID },
  function(result1) {


  /* perform new request at the end of first request */

  $.postq("get_data", "get_items.php", { "id": customerID }, 
      function(result2) {

    /* add in code to perform at the end of the second ajax POST request */

  }); // end of request 2

}); // end of request 1

Here's your example using the ajaxq.js library:

function AddToCart(input) {
   $.postq("add_item", "/cart/add/js", input, function(result) {
        preview_items();
    }, "json");

}  

function preview_items() {
 $.getJSON('/cart.js', function(data) {
        $('.cart-item-count').text(data.item_count);
        $('.cart-item-price').html(formatMoney(data.total_price));      
        ShowCart();
}


$(document).ready(function() { 
  $("#addToCart").on("click" function() {
    $('#capsContainer input:checked').each(function(elem) {
      var cartItem = {
        id: $(this).val(),
       quantity: 1
      }

      cart.push(cartItem);
    });

    var test1 = AddToCart(cart[0]);
    var test2 = AddToCart(cart[1]);

  });
Ad
source: stackoverflow.com
Ad