jameshwart lopez
jameshwart lopez

Reputation: 3151

Finish first ajax before firing the second, finish second ajax before firing third ajax inside loop

I have this json response from our api that I need to loop through and create woocommerce product or variant product, for each products.

{
  "pagination": {
    "page": 1,
    "per_page": 50,
    "results": 2,
    "pages": 1,
    "deleted_product": 0
  },
  "products": [
    {
      "id": "02dcd191-aebf-11e6-f485-5abe3e19de38aotbb94CZY3STcO1MxQS1S",
      "name": "testProduct112312312312345325345",
      "description": null,
      "sku": "testProduct112312312312345325345",
      "active": 1,
      "cost_price": 0,
      "list_price": null,
      "sell_price": 17.28,
      "tax_value": 1.728,
      "tax_name": "Sales_tax_sample",
      "tax_rate": 0.1,
      "tax_id": "02dcd191-aebf-11e6-f485-1c85a7f11c83",
      "includes_tax": true,
      "quantity": null,
      "product_type": null,
      "update_at": "2016-08-05 03:42:14",
      "deleted_at": null,
      "images": [],
      "variants": [],
      "tags": [],
      "outlets": [
        {
          "outlet_id": "0a422413-2fb9-11e6-ff63-0b90c839fa9e",
          "name": "Main Outlet",
          "quantity": 10
        }
      ],
      "price_books": [
        {
          "id": "65f85250-5ce8-9295-59be-40d76716eb00",
          "price": 17.28
        }
      ],
      "brands": []
    },
    {
      "id": "02dcd191-aebf-11e6-f485-5abe44095b97aotbb94CZY3STcO1MxQS1S",
      "name": "var1444444444444444444444444444444444444444444",
      "description": "<p>jameshwart</p>",
      "sku": "testvar_23234",
      "active": 1,
      "cost_price": 0,
      "list_price": null,
      "sell_price": 7.49545,
      "tax_value": 0.74955,
      "tax_name": "Sales_tax_sample",
      "tax_rate": 0.1,
      "tax_id": "02dcd191-aebf-11e6-f485-1c85a7f11c83",
      "includes_tax": true,
      "quantity": null,
      "product_type": null,
      "update_at": "2016-08-05 05:55:55",
      "deleted_at": null,
      "images": [],
      "variants": [
        {
          "id": "02dcd191-aebf-11e6-f485-5abe44095b97aotbb94CZY3STcO1MxQS1S",
          "name": "var1444444444444444444444444444444444444444444 / Blue",
          "sku": "10017",
          "quantity": null,
          "tax_value": 0.74955,
          "tax_name": "Sales_tax_sample",
          "tax_rate": 0.1,
          "tax_id": "02dcd191-aebf-11e6-f485-1c85a7f11c83",
          "includes_tax": true,
          "list_price": null,
          "sell_price": 7.49545,
          "cost_price": 0,
          "option_one_name": "Colour",
          "option_one_value": "Blue",
          "option_two_name": null,
          "option_two_value": null,
          "option_three_name": null,
          "option_three_value": null,
          "update_at": "2016-08-05 05:55:55",
          "deleted_at": null,
          "outlets": [
            {
              "outlet_id": "0a422413-2fb9-11e6-ff63-0b90c839fa9e",
              "name": "Main Outlet",
              "quantity": 0
            }
          ],
          "price_books": [
            {
              "id": "b343e66b-33d1-41af-9969-9df911a29b7baotbb94CZY3STcO1MxQS1S",
              "price": 7.49545
            }
          ]
        },
        {
          "id": "02dcd191-aebf-11e6-f485-5abe45693e6caotbb94CZY3STcO1MxQS1S",
          "name": "var1444444444444444444444444444444444444444444 / Red",
          "sku": "sku_119",
          "quantity": null,
          "tax_value": 0.99773,
          "tax_name": "Sales_tax_sample",
          "tax_rate": 0.1,
          "tax_id": "02dcd191-aebf-11e6-f485-1c85a7f11c83",
          "includes_tax": true,
          "list_price": null,
          "sell_price": 9.97727,
          "cost_price": 0,
          "option_one_name": "Colour",
          "option_one_value": "Red",
          "option_two_name": null,
          "option_two_value": null,
          "option_three_name": null,
          "option_three_value": null,
          "update_at": "2016-08-05 05:55:55",
          "deleted_at": null,
          "outlets": [
            {
              "outlet_id": "0a422413-2fb9-11e6-ff63-0b90c839fa9e",
              "name": "Main Outlet",
              "quantity": 0
            }
          ],
          "price_books": [
            {
              "id": "fdd0f01b-a2c2-0263-b17c-3f63fdf0e6b8",
              "price": 9.97727
            }
          ]
        }
      ],
      "tags": [],
      "outlets": [
        {
          "outlet_id": "0a422413-2fb9-11e6-ff63-0b90c839fa9e",
          "name": "Main Outlet",
          "quantity": 0
        }
      ],
      "price_books": [
        {
          "id": "b343e66b-33d1-41af-9969-9df911a29b7baotbb94CZY3STcO1MxQS1S",
          "price": 7.49545
        }
      ],
      "brands": []
    }
  ]
}

As you can see from the json above there might be many possible pages and a maximum of 50 products per page. I have coded to get the first page like the example json above and loop through on each product. Below is my code

function product_to_woo( page ){

            //check if page is undefined then we set it to one
            if(typeof page == 'undefined'){
                page = 1;
            }else if( page <= 0){
                //Make sure we always start to page 1
                page = 1;
            }
            var product_number = 0;

            get_product_by_page(page, function(res){
                var product_count = res.products.length;

                if(product_count > 0){

                    for( var i = 0; i < product_count; i++){


                        product = res.products[i];
                        if( product.deleted_at == null ){
                            product_number = i+1;
                        }


                        if(res.pagination.page > 1){
                            product_number += PER_PAGE;//PER_PAGE is constant value 50
                        }

                        var p_data = {
                            action              :   'import_to_woo',
                            page                :   res.pagination.page,
                            product_total_count :   res.pagination.results,
                            product             :   product,
                            product_number      :   product_number,
                            deleted_product     :   res.pagination.deleted_product
                        };

                        post_data(p_data,function(p_res){
                           //I have done some message for the users
                        });
                    }

                }



                if(res.pagination.page <= res.pagination.pages){

                    page = parseInt(res.pagination.page) + 1;

                    if(page <= res.pagination.pages){
                        product_to_woo(page);
                    }

                }

            });

    }

My problem is the ajax request being set inside for loop. Its sending another ajax request before the first ajax request is done and sends the third ajax request even though the second ajax is not yet finish.

Is there another way to do this?, but the difference is let the first ajax finish before another second ajax is fired, then after the second request is done will also fired the fourth ajax request, and so on until there are no products left.

Upvotes: 2

Views: 103

Answers (1)

Ozan
Ozan

Reputation: 3739

You can run your second ajax inside the successCallback of the first ajax. And run your third ajax inside the successCallback of the first ajax. So on and so forth.

//first ajax
$.post("someurl.php", { data: someData }, function (response1) {
    //do work with the response of the ajax
    //...

    //second ajax
    $.post("someotherurl.php", { data: someOtherData }, function (response2) {
        //...

        //third ajax
        $.post("yetanotherurl.php", { data: yetAnotherData }, function (response3) {
            //...
        });
    });
});

A better way manage this callback hell would be to use the deferred like behavior of the the jqXhr object.


In your specific case, you are making concurrent ajax calls inside a loop. Assuming that you do not know the exact number of calls, the above mentioned methods will be inapplicable or very cumbersome at best. But you can make use of jQuery.Deferred() and jQuery.when() to make sure all the previous ajax calls and all relevant work has been completed before running an ajax.

var defs = [];
for (var i = 0; i < 3; i++) {
    var d = $.Deferred();

    //make sure to wait for all the previous ajax calls to get resolved
    $.when.apply(this, defs).done(function () {
        $.post("url", { data: someData }, function (response) {
            //do work with response
            //...

            d.resolve(); //resolve the deferred to let the next ajax know it is done
        });
    });

    defs.push(d);
}

Upvotes: 4

Related Questions