Promises and Async/Await
To resolve "Callback Hell", ES6 introduced the Promise.
A Promise is an object representing the eventual completion (or failure) of an asynchronous operation.
Every Promise resides in one of three states:
- Pending: Waiting for the task to finish.
- Fulfilled (Resolved): The operation completed successfully.
- Rejected: The operation failed.
Consuming a Promise (.then())
const myPromise = new Promise((resolve, reject) => {
let success = true;
if (success) {
resolve("The task finished gracefully!");
} else {
reject("Hardware error occurred!");
}
});
// Consuming the promise cleanly without nested callbacks
myPromise
.then((message) => {
console.log("SUCCESS:", message);
})
.catch((error) => {
console.log("FAILED:", error);
});
Modern Syntax: async / await
In ES8 (2017), JavaScript introduced the async and await keywords, acting as "syntactic sugar" on top of Promises. It allows us to write asynchronous code that visually looks entirely synchronous!
async: Placing this keyword in front of a function forces it to automatically return a Promise.await: Can only be used inside anasyncfunction. It pauses the local function execution until the Promise resolves, then evaluates securely.
// A fake promise simulating a network delay
const downloadData = () => {
return new Promise(resolve => setTimeout(() => resolve("Data 100%"), 2000));
};
// Modern implementation
async function initTask() {
console.log("Starting download...");
// Execution inside initTask() pauses right here for 2 seconds.
// The rest of the browser remains perfectly unfrozen outside!
const result = await downloadData();
console.log("Finished! Result:", result);
}
initTask();
Error Handling with
async/awaituses standardtry {} catch {}logic blocks instead of relying on.catch().