Now let’s cover Promises and async/await
in Node.js, which are essential for handling asynchronous operations cleanly. We’ll go step by step and tie it to the Node environment.
1️⃣ What Are Promises?
-
Promise = an object representing the eventual completion or failure of an asynchronous operation.
-
Avoids “callback hell” by chaining
.then()
and.catch()
.
States of a Promise
-
Pending → initial state
-
Fulfilled → operation completed successfully
-
Rejected → operation failed
2️⃣ Basic Promise Example in Node.js
const fs = require("fs").promises; // fs.promises for async file ops
fs.readFile("example.txt", "utf8")
.then((data) => {
console.log("File contents:", data);
})
.catch((err) => {
console.error("Error reading file:", err);
});
-
fs.promises.readFile
returns a Promise -
.then()
handles success,.catch()
handles errors
3️⃣ async/await
Syntax
-
Cleaner syntax for Promises
-
Allows writing asynchronous code as if it were synchronous
const readFileAsync = async () => {
try {
const data = await fs.readFile("example.txt", "utf8");
console.log("File contents:", data);
} catch (err) {
console.error("Error reading file:", err);
}
};
readFileAsync();
-
async
→ marks function as asynchronous -
await
→ pauses function execution until the Promise resolves/rejects
4️⃣ Multiple Async Operations
Sequential Execution
const sequential = async () => {
const data1 = await fs.readFile("file1.txt", "utf8");
const data2 = await fs.readFile("file2.txt", "utf8");
console.log(data1, data2);
};
Parallel Execution
const parallel = async () => {
const [data1, data2] = await Promise.all([
fs.readFile("file1.txt", "utf8"),
fs.readFile("file2.txt", "utf8")
]);
console.log(data1, data2);
};
- Use
Promise.all
for parallel async operations → faster than sequential
5️⃣ Error Handling
const fetchData = async () => {
try {
const data = await someAsyncFunction();
console.log(data);
} catch (err) {
console.error("Something went wrong:", err);
}
};
- Always wrap
await
calls intry/catch
or.catch()
to prevent unhandled rejections
6️⃣ Node-Specific Examples
- Database Queries (Mongoose / Sequelize)
const getUsers = async () => {
const users = await User.find(); // Mongoose
// or await User.findAll(); // Sequelize
return users;
};
- HTTP Requests (Axios)
const axios = require("axios");
const fetchData = async () => {
try {
const response = await axios.get("https://jsonplaceholder.typicode.com/posts");
console.log(response.data);
} catch (err) {
console.error(err);
}
};
7️⃣ Key Takeaways
-
Promises → manage async operations, chain
.then()
/.catch()
-
async/await
→ cleaner syntax, easier to read, reduces callback nesting -
Use
Promise.all
for parallel operations -
Always handle errors with try/catch or
.catch()
-
Works seamlessly with Node.js I/O, DB calls, APIs