JavaScript Promise (Live Playground)
Promise in JavaScript is a powerful way to handle asynchronous operations. They provide a cleaner and more manageable approach compared to using callbacks.
Creating Promise
To create a Promise, use the Promise
constructor and pass a single argument, known as the executor function. The executor function takes two parameters: a resolve
function and a reject
function.
Example:
const myPromise = new Promise((resolve, reject) => {
// Asynchronous operation here...
});
Using the resolve
and reject
Functions
Call the resolve
function when the asynchronous operation is successful and pass the result as an argument. Call the reject
function when the operation fails and pass the error as an argument.
Example:
const fetchData = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
const success = true; // Simulate success or failure
if (success) {
resolve('Data fetched');
} else {
reject('Error fetching data');
}
}, 1000);
});
};
Consuming Promise
Use the then
method to attach callbacks that will be called when the Promise is fulfilled. Use the catch
method to attach callbacks that will be called when the Promise is rejected.
Example:
fetchData()
.then(data => {
console.log(data);
})
.catch(error => {
console.error(error);
});
Promise States
A Promise can be in one of the following states:
- Pending: The initial state of the Promise. Neither fulfilled nor rejected.
- Fulfilled: The Promise has successfully completed and has a resulting value.
- Rejected: The Promise has failed, and a reason for the failure is provided.
Transitioning Between States
When you create a Promise, it is in the pending state. It transitions to the fulfilled or rejected state by calling the resolve
or reject
functions, respectively, in the executor function.
Example:
const myPromise = new Promise((resolve, reject) => {
// Asynchronous operation here...
if (/* operation successful */) {
resolve(result);
} else {
reject(error);
}
});
Consuming Promise States
When a Promise is in the fulfilled state, the callbacks attached with the then
method are executed. When a Promise is in the rejected state, the callbacks attached with the catch
method are executed.
Example:
myPromise
.then(result => {
console.log('Success:', result);
})
.catch(error => {
console.error('Error:', error);
});
Promise State Immutability
Once a Promise transitions from the pending state to either the fulfilled or rejected state, its state cannot change. This ensures that the Promise's value or reason remains consistent throughout its lifecycle.
Example:
const myPromise = new Promise((resolve, reject) => {
resolve('First resolve');
resolve('Second resolve'); // This call is ignored
reject('First reject'); // This call is ignored
});
Chaining Promises in JavaScript
Chaining Promises in JavaScript helps you to manage multiple asynchronous operations sequentially.
Chaining Promises
Chaining Promises involves attaching multiple then
and catch
methods to a single Promise. When a Promise is fulfilled, the next then
method in the chain is called, and when a Promise is rejected, the next catch
method is called.
Example:
const myPromise = new Promise((resolve, reject) => {
resolve('Initial Value');
});
myPromise
.then(value => {
console.log('First then:', value);
return value + ' - Second then';
})
.then(newValue => {
console.log(newValue);
return newValue + ' - Third then';
})
.then(finalValue => {
console.log(finalValue);
})
.catch(error => {
console.error('Error:', error);
});
Error Handling in Promise Chains
If a Promise is rejected or an error is thrown in a then
method, the chain skips all remaining then
methods and proceeds to the next catch
method.
Example:
const myPromise = new Promise((resolve, reject) => {
resolve('Initial Value');
});
myPromise
.then(value => {
console.log('First then:', value);
throw new Error('An error occurred');
})
.then(newValue => {
console.log('This will not be executed');
})
.catch(error => {
console.error('Error:', error.message);
});
Returning Promises in Chains
You can return a Promise from a then
method, allowing you to perform asynchronous operations in sequence.
Example:
const myPromise = new Promise((resolve, reject) => {
resolve('Initial Value');
});
function fetchData() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('Data fetched');
}, 1000);
});
}
myPromise
.then(value => {
console.log('First then:', value);
return fetchData();
})
.then(data => {
console.log('Data:', data);
})
.catch(error => {
console.error('Error:', error);
});
Promise Error Handling
Handling errors in JavaScript Promises is essential to create resilient applications.
Using catch
The catch
method is used to handle errors or rejected Promises. It is called when an error is thrown or a Promise is rejected in the preceding chain.
Example:
const myPromise = new Promise((resolve, reject) => {
reject('An error occurred');
});
myPromise
.then(value => {
console.log('Value:', value);
})
.catch(error => {
console.error('Error:', error);
});
Using finally
The finally
method is called regardless of whether the Promise is fulfilled or rejected. It is useful for performing cleanup tasks or other operations that should occur no matter the outcome.
Example:
const myPromise = new Promise((resolve, reject) => {
reject('An error occurred');
});
myPromise
.then(value => {
console.log('Value:', value);
})
.catch(error => {
console.error('Error:', error);
})
.finally(() => {
console.log('Finished processing the Promise');
});
Handling Errors in a Promise Chain
If an error is thrown or a Promise is rejected in a chain, the execution skips to the next catch
method. This allows for centralized error handling.
Example:
const myPromise = new Promise((resolve, reject) => {
resolve('Initial Value');
});
myPromise
.then(value => {
console.log('First then:', value);
throw new Error('An error occurred');
})
.then(newValue => {
console.log('This will not be executed');
})
.catch(error => {
console.error('Error:', error.message);
});
Conclusion
Promise provides an elegant way to handle asynchronous operations in JavaScript. By creating and using Promise, you can avoid callback hell and write more maintainable and readable code.