Async & Await
Here is the promise chaining in action:
console.log("listening for events");
getUser(1)
.then(user => getLoans(user["Account number"]))
.then(loans => getTransactions(loans["Most recent"]))
.then(transactions => console.log(transactions))
.catch(error => {
console.log(error.message); // probably need to do more!
});
console.log("still listening for events!");
We can simplify this code snippet using the new JavaScript feature async
/await
(which they have borrowed from C#).
Async/Await allows you to write asynchronous code that looks like synchronous code!
Whenever you call a function that returns a Promise, you can "await" its results and get the results, just like calling synchronous operations.
For example, instead of
getUser(1)
.then(user => console.log(user))
we can write
const user = await getUser(1);
console.log(user);
So, we can rewrite the code snippet at the top as follows
console.log("listening for events");
try {
const user = await getUser(1);
const loans = await getLoans(user["Account number"]);
const transactions = await getTransactions(loans["Most recent"]);
console.log(transactions);
} catch (error) {
console.log(error.message);
}
console.log("still listening for events!");
There is one caveat, however! You cannot use the await
operator in any random place that you want.
The
await
operator can only be used inside a function, and that function must be decorated with theasync
modifier.
So we must do something like this:
async function displayTransactions(userID) {
try {
const user = await getUser(userID);
const loans = await getLoans(user["Account number"]);
const transactions = await getTransactions(loans["Most recent"]);
console.log(transactions);
} catch (err) {
console.log(err);
}
}
console.log("listening for events");
displayTransactions(1)
console.log("still listening for events!");
The async/await pattern is a syntax sugar! But, under the hood, it is converted to a chain of Promises!
function getUser(id) { console.log("Reading a user from a database..."); return new Promise((resolve, reject) => { setTimeout(() => { console.log("Received user data..."); resolve({ ID: id, "Account number": "58721094531267" }); }, 2000); }); } function getLoans(account) { console.log("Request for loan data..."); return new Promise((resolve, reject) => { setTimeout(() => { console.log("Received loan data..."); resolve({ "Most recent": "loan 3", All: ["loan 1", "loan 2", "loan 3"] }); }, 2000); }); } function getTransactions(loan) { console.log("Request for transactions data..."); return new Promise((resolve, reject) => { setTimeout(() => { console.log("Received transactions data..."); resolve(["tran 3", "tran 2", "tran 1"]); }, 2000); }); } async function displayTransactions(userID) { try { const user = await getUser(userID); const loans = await getLoans(user["Account number"]); const transactions = await getTransactions(loans["Most recent"]); console.log(transactions); } catch (err) { console.log(err); } } console.log("listening for events"); displayTransactions(1) console.log("still listening for events!");
Resources
- YouTube video "The Async Await Episode I Promised" by Fireship.