Reputation: 9065
If I have a function with 3 Promises, they are supposed to run one after another, in the other they are appeared in the code of the function? I have a code where, in the third and last promise, I should have access to variables size
and total
, assigned inside the other 2 promises, but they remain undefined
. Am I missing something about this concept of Promisses? I just start learning about them very recently.
my code:
function update_cart() {
var cart_size = document.getElementById('cart_size');
var cart_status = document.getElementById('cart_status');
var cart_total = document.getElementById('cart_total');
var size, total;
var promise1 = new Promise(function(resolve, reject) {
if(cart_size !== null) {
var cliente = cart_size.dataset.cliente;
var url = cart_size.dataset.url;
var xhr = new XMLHttpRequest();
xhr.open("POST", url, true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
resolve(xhr.responseText);
}
};
var formData = new FormData();
formData.append("cliente", cliente);
xhr.send(formData);
} else {
reject();
}
});
promise1.then(function(value) {
size = value;
cart_size.innerHTML = size;
if(size == 0)
cart_size.style.display = 'none';
else
cart_size.style.display = 'block';
}).catch(function(){
console.log('erro1');
});
var promise2 = new Promise(function(resolve, reject) {
if(cart_total !== null) {
var cliente = cart_total.dataset.cliente;
var url = cart_total.dataset.url;
var xhr = new XMLHttpRequest();
xhr.open("POST", url, true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
resolve(xhr.responseText);
}
};
var formData = new FormData();
formData.append("cliente", cliente);
xhr.send(formData);
} else {
reject();
}
});
promise2.then(function(value) {
total = value;
var currency = new Intl.NumberFormat('pt-BR', { style: 'currency', currency: 'BRL' }).format(total);
cart_total.innerHTML = currency;
}).catch(function(){
console.log('erro2');
});
var promise3 = new Promise(function(resolve, reject) {
if(cart_status !== null) {
resolve();
} else {
reject();
}
});
promise3.then(function() {
console.log('promise3');
console.log('size: '+size+', total: '+total);
switch(size) {
case 0:
cart_status.innerHTML = 'A cesta de compras está vazia.';
document.getElementById('table').style.display = 'none';
break;
case 1:
cart_status.innerHTML = size + ' produto adicionado na cesta, com valor ' + total;
document.getElementById('table').style.display = 'block';
break;
default:
cart_status.innerHTML = size + ' produtos adicionados na cesta, com valor ' + total;
document.getElementById('table').style.display = 'block';
break;
}
}).catch(function(){
console.log('erro3');
});
}
Upvotes: 2
Views: 59
Reputation: 154
The three promises are being executed at the same time since you are initializing them before waiting for any to finish. If you want the promises to run one after the other and be able to catch different errors for different promises you should use async/await:
async function update_cart() {
// ...
try {
var value = await promise1;
size = value;
// Rest of code inside promise1.then
} catch(err) {
console.log('erro1');
}
}
Repeat that for promise2 and promise3. The function update_cart will now return a Promise that resolves when promise1, promise2 and promise3 all resolve, one after the other
Upvotes: 1
Reputation: 5402
Promise execution does not block the calling function. Hence your all 3 promises are executed immediately resulting in the undefined
value in size
and total
variables. Try this :
function update_cart() {
var cart_size = document.getElementById("cart_size");
var cart_status = document.getElementById("cart_status");
var cart_total = document.getElementById("cart_total");
var size, total;
var promise1 = new Promise(function(resolve, reject) {
if (cart_size !== null) {
var cliente = cart_size.dataset.cliente;
var url = cart_size.dataset.url;
var xhr = new XMLHttpRequest();
xhr.open("POST", url, true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
resolve(xhr.responseText);
}
};
var formData = new FormData();
formData.append("cliente", cliente);
xhr.send(formData);
} else {
reject();
}
});
var promise2 = new Promise(function(resolve, reject) {
if (cart_total !== null) {
var cliente = cart_total.dataset.cliente;
var url = cart_total.dataset.url;
var xhr = new XMLHttpRequest();
xhr.open("POST", url, true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
resolve(xhr.responseText);
}
};
var formData = new FormData();
formData.append("cliente", cliente);
xhr.send(formData);
} else {
reject();
}
});
var promise3 = new Promise(function(resolve, reject) {
if (cart_status !== null) {
resolve();
} else {
reject();
}
});
promise1
.then(function(value) {
size = value;
cart_size.innerHTML = size;
if (size == 0) cart_size.style.display = "none";
else cart_size.style.display = "block";
promise2
.then(function(value) {
total = value;
var currency = new Intl.NumberFormat("pt-BR", {
style: "currency",
currency: "BRL"
}).format(total);
cart_total.innerHTML = currency;
promise3
.then(function() {
console.log("promise3");
console.log("size: " + size + ", total: " + total);
switch (size) {
case 0:
cart_status.innerHTML = "A cesta de compras está vazia.";
document.getElementById("table").style.display = "none";
break;
case 1:
cart_status.innerHTML =
size + " produto adicionado na cesta, com valor " + total;
document.getElementById("table").style.display = "block";
break;
default:
cart_status.innerHTML =
size + " produtos adicionados na cesta, com valor " + total;
document.getElementById("table").style.display = "block";
break;
}
})
.catch(function() {
console.log("erro3");
});
})
.catch(function() {
console.log("erro2");
});
})
.catch(function() {
console.log("erro1");
});
}
I just moved the next promise's invocations the the previous promise's callback, so that each one gets executed only after the previous one is complete. If you require some other order, or need to parallelize requests read more about promises here.
Upvotes: 1