简体   繁体   中英

How do I rewrite my AJAX that I will get a response in a particular order?

I'm making a cart in a e-commerce website.

This script delete one piece of product if user clicked on a button

        $(".minusCart").click(function () {
            var id = $(this).attr("data-id");
            $.post("/cart/deleteOneAjax/" + id, {}, function (data) {
                if (!data) {
                    location.reload();
                } else {
                    $("#id-count" + id).val(data);
                }
            });
            $.post("/cart/countAjax/" + id, {}, function (data) {
                $("#cart-count").html(data);
            });
            $.post("/cart/productPriceAjax/" + id, {}, function (data) {
                $("#product-price-cart" + id).html(data);
            });
            $.post("/cart/totalPriceAjax/" + id, {}, function (data) {
                $(".total-price-cart").html(data);
            });

        });

So steps this script should do are:

  1. Delete one piece of product
  2. Calculate how many pieces are left
  3. Calculate a sum for each product (quantity of product * price)
  4. Calculate a sum for the whole cart

So the order is really important. But because those are asynchronous requests, responses could be sent back in a different order. Because of that sometimes I get response for /cart/deleteOneAjax/ the last and all other data is not calculated properly.

What do I do in order to solve it?

Using ajax instead of using this post method will make your request handling much more customizable.

As a solution of this problem you can use 'await' keyword before your post function call, then you have to make the click event function 'async'.

And easy solution for now is to make this calls synchronous, replace the 'post' methods with 'ajax' calls.

$.ajax({
  type: 'POST',
  url: url,
  data: data,
  success: success,
  dataType: dataType,
  async:false             //Here I am making it synchronus
});

See the official documentation here: https://api.jquery.com/jquery.ajax/

ajax is asynchronous function , which mean the JS is not necessary to process your code from line 1 to line 100 according to the sequence that you expecting if there are async function in between.

In your case, the JS indeed process all your ajax request in the correct sequence, it just it isn't wait for cart/deleteOneAjax to response then only process the next ajax cart/countAjax , and so on.

How to solve?

The old way: Promise Then

The new way: async await

Here i demonstrate with Promise Then way:

    function deleteOne(id) {
        return new Promise((resolve, reject) => {
            $.post("/cart/deleteOneAjax/" + id, {}, function (data) {
                if (!data) {
                    reject("no data")
                } else {
                    resolve(data)
                }
            });
        })
    }


    function count(id) {
        return new Promise((resolve, reject) => {
            $.post("/cart/countAjax/" + id, {}, function (data) {
                if (!data) {
                    reject("no data")
                } else {
                    resolve(data)
                }
            });
        })
    }
    function productPrice(id) {
        return new Promise((resolve, reject) => {
            $.post("/cart/productPriceAjax/" + id, {}, function (data) {
                if (!data) {
                    reject("no data")
                } else {
                    resolve(data)
                }
            });
        })
    }

    function totalPrice(id) {
        return new Promise((resolve, reject) => {
            $.post("/cart/totalPriceAjax/" + id, {}, function (data) {
                if (!data) {
                    reject("no data")
                } else {
                    resolve(data)
                }
            });
        })
    }

    $(".minusCart").click(function () {
        var id = $(this).attr("data-id");
        deleteOne(id).then(deleted => {

            // your logic before process next ajax
            count(id).then(countData => {

                // your logic before process next ajax
                productPrice(id).then(productPriceData => {

                    // your logic before process next ajax
                    totalPrice(id).then(totalPriceData => {

                    })
                })
            })
        }).catch(deleteError=>{
            //logic for deleteOne rejection scenario
        })
    })

One down side of Promise Then is callback hell , but that is for your future study.

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