JavaScript Promises and Async Programming
(Handle asynchronous tasks like API calls, delays, and file loading)
Why Asynchronous Programming?
JavaScript is single-threaded, meaning it executes one task at a time.
But real-world tasks (like fetching data or waiting for a timer) can take time.
Asynchronous programming lets your code continue running without blocking.
Common Async Tasks in JavaScript
- Fetching data from an API
- Reading/writing files (in Node.js)
- setTimeout / setInterval
- Event handling
Callbacks (Old Method)
function getData(callback) {
setTimeout(() => {
callback("Data loaded");
}, 1000);
}
getData((result) => {
console.log(result); // Data loaded
});
⚠️ Problem: Callback Hell — nested callbacks are hard to read and debug.
Promises (Modern Way)
A Promise is an object that represents the future value of an async operation.
States of a Promise:
- Pending
- Fulfilled
- Rejected
Creating a Promise
const myPromise = new Promise((resolve, reject) => {
let success = true;
setTimeout(() => {
if (success) resolve("Success!");
else reject("Error occurred");
}, 1000);
});
Consuming a Promise
myPromise
.then((value) => {
console.log(value); // Success!
})
.catch((error) => {
console.error(error);
})
.finally(() => {
console.log("Promise completed");
});
Real Example with fetch()
fetch("https://jsonplaceholder.typicode.com/posts/1")
.then((response) => response.json())
.then((data) => console.log(data))
.catch((err) => console.error(err));
Async/Await (Syntactic Sugar for Promises)
async
makes a function return a promise.
await
waits for the promise to resolve.
async function getPost() {
try {
const response = await fetch("https://jsonplaceholder.typicode.com/posts/1");
const data = await response.json();
console.log(data);
} catch (err) {
console.error("Error:", err);
}
}
getPost();
More readable than .then()
chaining.
setTimeout / setInterval (Delay functions)
setTimeout(() => {
console.log("Runs after 2 seconds");
}, 2000);
let counter = 0;
const intervalId = setInterval(() => {
counter++;
console.log(counter);
if (counter === 3) clearInterval(intervalId);
}, 1000);
Promise.all and Promise.race
const p1 = Promise.resolve("First");
const p2 = Promise.resolve("Second");
Promise.all([p1, p2]).then(values => console.log(values)); // [ "First", "Second" ]
Promise.race([p1, p2]).then(value => console.log(value)); // "First" (whichever resolves first)
Summary
- Promises handle async tasks more cleanly than callbacks.
async/await
makes code cleaner and easier to read.- Always use
catch()
ortry...catch
to handle errors. Promise.all
waits for all promises;Promise.race
returns the first one.
🧪 Practice Exercise:
Task:
- Create a Promise that resolves after 2 seconds and logs a message.
- Use
fetch()
to get a list of users from a public API. - Write an async function that uses
await
to fetch and display data. - Try catching errors using
try...catch
withasync/await
. - Chain multiple
.then()
methods to process fetched data.