I'm experiencing an unexpected order of execution when using Promises and async/await in JavaScript. Here’s the code snippet:
let a = "Hanzala"
let newPromise = new Promise((resolve, reject) => {
let error = false
if (!error) {
setTimeout(() => {
console.log("Async Task");
resolve(a)
}, 1000)
} else {
reject("Error")
}
});
newPromise
.then((data) => {
console.log("Async resolved",data)
return data.toUpperCase()
})
.then((data) => {
console.log(data+" from second then")
})
.catch((e) => {
console.log(e + " Async rejected");
});
(async () => {
try {
const res = await newPromise
console.log(res+ " from async await")
} catch (error) {
console.log(error+"Error form async");
}
})();
The Output is :
Async Task
Async resolved Hanzala
Hanzala from async await
HANZALA from second then
Question:
Why does the output order differ from my expectation? Specifically, why does the log "Hanzala from async await" appear before "HANZALA from second then"?
expected Output:
Async Task
Async resolved Hanzala
HANZALA from second then
Hanzala from async await
Additional Information:
With const res = await newPromise
you only wait for the Promise create by:
let newPromise = new Promise((resolve, reject) => {
let error = false
if (!error) {
setTimeout(() => {
console.log("Async Task");
resolve(a)
}, 1000)
} else {
reject("Error")
}
});
because that is the Promise stored in newPromise
, and not the Promise returned at the end of the chain from:
.catch((e) => {
console.log(e + " Async rejected");
});
To get the exact same result you would need to do something like this:
let a = "Hanzala"
let newPromise = new Promise((resolve, reject) => {
let error = false
if (!error) {
setTimeout(() => {
console.log("Async Task");
resolve(a)
}, 1000)
} else {
reject("Error")
}
});
let anotherPromise = newPromise
.then((data) => {
console.log("Async resolved",data)
return data.toUpperCase()
})
.then((data) => {
console.log(data+" from second then")
})
.catch((e) => {
console.log(e + " Async rejected");
});
(async () => {
try {
const res = await newPromise;
await anotherPromise;
console.log(res+ " from async await")
} catch (error) {
console.log(error+"Error form async");
}
})();
This stores the result of the generated Promise in another variable. And you can then wait for both, in the order you would like.
As a note:
This way of structuring code is not the best way, first of all in one "unit" (project, module or at least per file basis) you should not mix await
/async
and then
. While storing Promises in variables is not necessarily wrong, you should take care that none of these are orphans.