Let's start with a quick video that goes over everything in a very succinct way:
{% hyf-youtube src="https://www.youtube.com/watch?v=DHvZLI7Db8E" %}
He gives a lot of information in a short amount of time, so let's go through some of the concepts in a more detailed way:
By now you should've had some practice using callbacks. To reiterate, we use callbacks as a way to create asynchronicity in our application: we want to enable our application to do multiple things simultaneously.
But what if you want to have callbacks within callbacks... within callbacks? This will lead to what is known as callback hell.
This is where Promises come in. The idea of the Promise is a product of the evolution within the JavaScript language. A bunch of JavaScript developers wanted to figure out how to solve the problem of callback hell and this is what they came up with. Here's a basic example:
const promise = new Promise(function(resolve, reject) {
if (true) {
resolve('It has succeeded!');
} else {
reject('It has failed...');
}
});A promise can be in 1 of 3 states:
- Pending: The asynchronous code is being executed, with no result yet
- Fulfilled (resolved): The asynchronous code has successfully been executed without problems
- Rejected: The asynchronous code has failed because of some error
When a Promises is executed it will first execute the asynchronous code inside. In this process it will go into the pending state. After, depending on if it succeeded or not, it will be resolved or rejected.
What if you need to perform several asynchronous operations, that depend on the result of the one that came before it? For that we can use the .then() method: a special function, given to us by the Promise object, that allows us to directly use the return value of the asynchronous operation that happened before. Here's an example:
new Promise(function(resolve, reject) {
setTimeout(() => resolve(1), 1000); // We wait 1 second and then resolve with value 1
})
.then(function(result) {
console.log(result); // Result: 1
return result * 2;
})
.then(function(result) {
alert(result); // Result: 2
return result * 2;
})
.catch(error => {
console.log(error);
});By chaining the Promise we can gain greater control over the results of our asynchronous operations!
The concept of a Promise, in execution, doesn't add anything new. It does exactly what callbacks aim to do, which is enabling asynchronous actions: for example, clicking a button to load in an image, while still being able to navigate the webpage.
So what are the benefits of using a Promise over a callback? Here's a few:
- It makes writing asynchronous JavaScript code more readable for you, the developer. In effect, you could call Promises the updated version of callbacks. Callbacks version 2.0.
- Better error handling, because of the
catchblock attached at the end. When something goes wrong within the Promise structure, it will throw an error. This error will then be caught and handled within thecatchblock.
If you just can't get enough, here are some extra links that mentors/students have found useful concerning this topic:
- JavaScript Promises for Dummies
- Let's learn ES6 - Promises
- JavaScript Promise in 100 Seconds
- A Simple Guide to ES6 Promises
- Visualize Promises: Promisees, PromiseTree, dev.to/lydiahallie
- Awesome Promises
- Promise Cookbook
- Coding Train
- javascript.info/async
- Promises in 10 minutes
- Async JS Crash Course
- Promise Basics
- Examples to Study: egghead-javascript-promises
- Traversy: Asynchronous Programming
- promises: FunFunFunction
- async/await: FunFunFunction