Introduction
A Promise is a JavaScript object that represents the eventual completion or failure of an asynchronous operation. Instead of using callback functions to handle asynchronous tasks, Promises provide a cleaner and more organized way to write asynchronous code.
Promises were introduced in JavaScript to solve problems such as callback hell, where multiple nested callback functions make code difficult to read and maintain.
Node.js uses Promises extensively for operations like reading files, making HTTP requests, querying databases, and interacting with external services. Modern automation frameworks such as Playwright, Puppeteer, WebdriverIO, and many Node.js libraries are built around Promises.
For automation engineers, understanding Promises is essential because most browser automation, API testing, file handling, and database operations return Promises.
In this tutorial, you’ll learn the basics of Promises, how they work, and how to use them in Node.js.
What is a Promise?
A Promise is an object that represents the future result of an asynchronous operation.
A Promise eventually produces either:
A successful result (fulfilled)
An error (rejected)
Until one of these occurs, the Promise remains pending.
Why Use Promises?
Promises help developers:
Write cleaner asynchronous code.
Avoid callback hell.
Improve readability.
Handle errors more effectively.
Chain asynchronous operations.
Improve code maintainability.
Simplify asynchronous workflows.
Promise States
Every Promise has one of the following states:
| State | Description |
|---|---|
| Pending | Initial state. The operation is still running. |
| Fulfilled | The operation completed successfully. |
| Rejected | The operation failed with an error. |
Once a Promise becomes fulfilled or rejected, its state cannot be changed.
Creating a Promise
A Promise is created using the Promise constructor.
Syntax
const promise =
new Promise(function (
resolve,
reject
) {
resolve("Success");
});
resolve()is called when the operation succeeds.reject()is called when the operation fails.
Example 1: Successful Promise
const promise =
new Promise(function (
resolve,
reject
) {
resolve(
"Operation completed."
);
});
promise.then(function (result) {
console.log(result);
});
Sample Output
Operation completed.
Example 2: Rejected Promise
const promise =
new Promise(function (
resolve,
reject
) {
reject(
"Something went wrong."
);
});
promise.catch(function (error) {
console.log(error);
});
Sample Output
Something went wrong.
Example 3: Promise with setTimeout()
const promise =
new Promise(function (
resolve
) {
setTimeout(function () {
resolve(
"Task completed."
);
}, 2000);
});
promise.then(function (result) {
console.log(result);
});
Sample Output
Task completed.
Example 4: Promise with Condition
const age = 20;
const promise =
new Promise(function (
resolve,
reject
) {
if (age >= 18) {
resolve(
"Eligible."
);
} else {
reject(
"Not eligible."
);
}
});
promise
.then(function (result) {
console.log(result);
})
.catch(function (error) {
console.log(error);
});
Sample Output
Eligible.
Example 5: Reading a File with Promises
const fs =
require("fs").promises;
fs.readFile(
"sample.txt",
"utf8"
)
.then(function (data) {
console.log(data);
})
.catch(function (error) {
console.log(error);
});
The file is read asynchronously, and the result is handled using a Promise.
Automation Testing Examples
Promises are used extensively in automation frameworks.
Playwright Example
Simulate page loading.
const pageLoad =
new Promise(function (resolve) {
resolve(
"Page loaded."
);
});
pageLoad.then(function (message) {
console.log(message);
});
Sample Output
Page loaded.
Selenium Example
Simulate browser startup.
const browser =
new Promise(function (resolve) {
resolve(
"Browser started."
);
});
browser.then(function (message) {
console.log(message);
});
Sample Output
Browser started.
Cypress Example
Simulate application launch.
const application =
new Promise(function (resolve) {
resolve(
"Application opened."
);
});
application.then(function (message) {
console.log(message);
});
Sample Output
Application opened.
API Testing Example
Handle an API response.
const api =
new Promise(function (resolve) {
resolve(
"API response received."
);
});
api.then(function (message) {
console.log(message);
});
Sample Output
API response received.
Data-Driven Testing Example
Load test data.
const data =
new Promise(function (resolve) {
resolve(
"CSV file loaded."
);
});
data.then(function (message) {
console.log(message);
});
Sample Output
CSV file loaded.
Promise vs Callback
| Feature | Callback | Promise |
|---|---|---|
| Readability | Lower | Higher |
| Callback Hell | Possible | Avoided |
| Error Handling | Manual | Centralized with .catch() |
| Chaining | Difficult | Easy with .then() |
| Modern JavaScript | Less preferred | Preferred |
Common Mistakes
Forgetting to Handle Errors
Always use .catch() to handle rejected Promises.
Mixing Callbacks and Promises
Avoid combining callback-based and Promise-based code unless necessary.
Not Returning Promises
When chaining operations, return Promises to ensure proper execution order.
Best Practices
Use Promises for asynchronous operations.
Always handle errors with
.catch().Keep Promise chains simple.
Return Promises from functions.
Avoid unnecessary nested Promises.
Use meaningful variable names.
Prefer
async/awaitfor complex asynchronous workflows.
Conclusion
Promises provide a modern and structured way to manage asynchronous operations in JavaScript. They improve readability, simplify error handling, and eliminate many of the problems associated with callback-based programming.
For automation engineers, Promises are fundamental because modern Node.js libraries and automation frameworks rely heavily on them for browser automation, API testing, file handling, and database interactions. Mastering Promise basics will prepare you for learning Promise chaining, Promise.all(), and async/await.
Frequently Asked Questions (FAQs)
What is a Promise?
A Promise is an object that represents the eventual result of an asynchronous operation.
What are the three Promise states?
Pending, Fulfilled, and Rejected.
What is resolve()?
resolve() marks a Promise as successfully completed.
What is reject()?
reject() marks a Promise as failed and passes an error.
Why are Promises important in automation testing?
Modern automation frameworks use Promises to manage asynchronous operations such as browser interactions, API requests, file handling, and database operations.
Key Takeaways
Promises represent future results of asynchronous operations.
Every Promise has three states: Pending, Fulfilled, and Rejected.
Use
resolve()for success andreject()for failure.Handle successful results using
.then().Handle errors using
.catch().Promises improve code readability and maintainability.
They eliminate many callback-related problems.
Modern Node.js libraries rely heavily on Promises.
Automation frameworks extensively use Promises.
Understanding Promise basics is essential before learning Promise chaining and
async/await.
