Intro.
Asynchronous operations in the context of programming, particularly in web development and software engineering, are operations that do not block the execution of other code while they are being processed. This concept is crucial for handling tasks that take an indeterminate amount of time, such as network requests, file operations, or timers, without freezing the user interface or stopping the execution of other code.
Promises in JavaScript are a powerful tool for managing asynchronous operations. They represent a value that may not be available yet but will be resolved at some point in the future. Let's break down the concept of Promises with explanations and examples.
Practical Use-Cases
Loading data from APIs.
Handling asynchronous operations like file reading, network requests.
Managing multiple asynchronous operations that depend on each other.
Understanding Promises
What is a Promise?
A Promise is an object representing the eventual completion or failure of an asynchronous operation. It's like a placeholder for a future value or error.
States of a Promise
Pending: The initial state of a promise. The outcome is not yet known.
Fulfilled: The operation completed successfully, and the promise now has a resolved value.
Rejected: The operation failed, and the promise has a reason for the failure.
How Promises Work
When a Promise is created, it starts in a pending state.
It can either be fulfilled with a value or rejected with a reason (like an error).
.then()
and.catch()
methods are used to handle the fulfilled or rejected state, respectively.
Examples of Using Promises
Basic Promise Creation and Usage
Chaining Promises
Promises in practice:
Creating a function that returns a Promise:
Define the Function
First, define your function as you normally would. For example:
2. Return a New Promise
Inside the function, return a new Promise. The Promise constructor takes a function (often called the "executor function") with two parameters:
resolve
andreject
. These are functions themselves that you can call to resolve or reject the Promise.3. Implement the Asynchronous Operation
Inside the executor function, implement the logic of your asynchronous operation. When the operation completes successfully, call
resolve
with the result. If an error occurs, callreject
with the error.
Note :
The ESLint error
prefer-promise-reject-errors
is indicating that when a Promise is rejected, it should be rejected with anError
object, not a string or other type of value. This is becauseError
objects contain valuable debugging information like stack traces, to avoide it use Error object like :
reject(new Error('failed'));
Using try-catch
in the context of JavaScript promises:
.then()
is used when the promise is successfully resolved. It returns an object with a success status and the resolved data..catch()
is used when the promise is rejected due to an error. It returns an object with an error status and the error message..finally()
is executed after either resolve or reject, typically used for cleanup or logging. It doesn't affect the outcome of the promise.
Case : Multiple Promises:
When dealing with multiple promises in JavaScript, there are a few common patterns and methods you can use to efficiently handle them. These patterns allow you to run asynchronous operations in parallel or in sequence, and to manage their outcomes effectively. Here are the key concepts:
Promise.all
:
Use
Promise.all
when you have multiple promises and you want to wait for all of them to complete.It takes an array of promises and returns a new promise that resolves when all of the promises in the array have resolved, or rejects as soon as one of the promises in the array rejects.
If all promises are resolved successfully, the return value is an array of the results of each promise, in the same order as the input.
Promise.allSettled
:
This method is similar to
Promise.all
, but it waits for all the promises to settle, regardless of whether they are resolved or rejected.It returns an array of objects that each describes the outcome of each promise, with a status of either 'fulfilled' or 'rejected'.
Return a Promise object that is rejected with a given reason:
Syntax:
Promise.reject(reason);
reason
: The reason why this Promise is being rejected. It can be an error, a string, or any other value. Often, it's anError
object, which is helpful for debugging.
Purpose:
Promise.reject()
is used when you want to create a Promise that is already in the rejected state.Example :
Promise.reject(new Error(`${data} cannot be processed`));
Case : Returning by the promise that resolved the first:
Typically refers to a scenario in JavaScript where you have multiple promises, and you are interested in the result of the first promise that resolves, regardless of the order in which they were initiated.
This can be achieved using
Promise.race()
, a method that returns a promise that fulfills or rejects as soon as one of the promises in an iterable fulfills or rejects, with the value or reason from that promise.
Example: Using Promise.race()
Let's consider an example where we have multiple promises, each representing a different asynchronous task. We want to take action as soon as the first task completes.

Promise.race([task1, task2, task3])
takes an iterable of promises and returns a new promise that resolves or rejects as soon as one of the input promises resolves or rejects. —— In this example, task2
completes first (after 200ms). Therefore, Promise.race
resolves with the value from task2
, which is "Task 2 completed"
.Use Case
This pattern is particularly useful in scenarios where you have multiple sources for the same kind of data or action, and you want to proceed with the first successful one. Examples include:
Fetching data from multiple servers and using the response from the server that responds first.
The await
Keyword:
keyword in JavaScript is a powerful feature used in conjunction with Promises to simplify the handling of asynchronous operations. It can only be used within an async
function or at the top level of a module.
Key Concepts of await
Purpose:
await
is used to pause the execution of anasync
function until a Promise is settled (either fulfilled or rejected).Usage: It is placed before a Promise or a thenable expression, which it then waits for.
Return Value: On fulfillment of the Promise,
await
returns the resolved value. If the Promise is rejected,await
throws the rejection value as an error.Non-Blocking: Despite pausing the execution of its own
async
function,await
does not block the main thread. Other operations outside theasync
function continue to run.
Syntax
async function functionName() {
const result = await somePromise;
// Code here waits until 'somePromise' is resolved
}