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:
- Delete one piece of product
- Calculate how many pieces are left
- Calculate a sum for each product (quantity of product * price)
- 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?
CodePudding user response:
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.
CodePudding user response:
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/