.then() vs. await
In the early days of web browsers, Promises and the await keyword didn’t exist. The only way to handle asynchronous I/O was to use “callback functions”—functions you passed as arguments to be executed later (like setTimeout).
When Promises were introduced, the .then() syntax was created as a massive improvement over traditional callbacks. Eventually, the async and await keywords were introduced as a massive improvement over .then().
The Callback Pyramid of Doom
If you need to make sequential asynchronous calls (e.g., fetch a user, then fetch their messages, then fetch the delivery status), using .then() requires chaining multiple nested callbacks.
fetchRecipient()
.then(function (recipient) {
return fetchMessageForRecipient(recipient.id);
})
.then(function (message) {
return fetchDeliveryStatus(message.id);
})
.then(function (status) {
console.log(`The status is ${status}`);
});
The Clean await Solution
By using async/await, you completely flatten the structure. The code reads top-to-bottom exactly like synchronous code.
const recipient = await fetchRecipient();
const message = await fetchMessageForRecipient(recipient.id);
const status = await fetchDeliveryStatus(message.id);
console.log(`The status is ${status}`);
Why do we still see .then()?
The async/await syntax wasn’t added to JavaScript until ES2017. Because of this, there are millions of lines of legacy code in the wild that still rely on .then().
As a modern JavaScript developer, you must know how to read .then() chains, but you should exclusively write new code using async and await whenever possible.