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.