Before we start, I want you to write an essay about everything you plan to do once you’ve learned how to make a promise. Ready? Great.
You need to know two terms. You’re probably thinking you already know what these words mean, and you’re probably right.
You resolve a promise when your value is ready. When your value is ready, your promise has been resolved.
You reject a promise when an error occurs. When an error happens, your promise has been rejected.
Promises: Resolve and Reject.
Promises are easy to make. In fact, you’ve ever even dabbled with promises before, you’ve already made plenty. Why?
We just made a new promise. It’s not the one called promise. It works like this:
- The original promise resolves a value.
- That value is given to .then.
- .then, like any ordinary function, returns a value.
So let’s save that promise and .then it.
Wow, easy! You actually made a promise! If it walks like a promise, and it talks like a promise, then it’s a promise, right?
Yay! We’re done!
“But I thought you were going to tell me how to make a new Promise.”
Why a callback, then?
It’s the easiest way to provide you with two functions that you’ll need to call. Think of them as keywords. Can you guess what they are?
That’s right. The two functions you get are called resolve and reject. Surprise.
- Call the resolve callback to provide a value to anyone who wants it.
You can pass one argument, but that argument can be anything you want.
- Call the reject argument to tell them that you can’t provide it.
You should pass one argument, which is probably going to be an error. Generally, this is stuff you want to throw.
Are we done? Is that every method of creating a promise?
No, there are four more. Let’s start with the easier two.
// This takes your value, creates a promise, and then
// immediately rejects it with your value.
let rejectedPromise = Promise.reject(new Error('An error'))
Creating an instantly rejected promise might be useful if you’re creating a function that returns a promise, but you encounter an error before you even get to the asynchronous part.
Alternatively, you could just throw an error, but it’s up to you and your implementation requirements.
// This takes your value, creates a promise, and then
// immediately resolves it with your value.
let resolvedPromise = Promise.resolve("A value")
Wrapping values inside promises seems useless at first glance, until you realize that this also works:
// This takes your promise and gives you the same promise back.
let redundantPromise = Promise.resolve(promise)
Imagine you’re writing a function. You take some data as an argument, but you don’t know if your data is a value or a promise. You can easily fix that:
The final methods: com-promise-s
The other two methods of creating promises are pretty similar. They both take an array (or technically, any iterable) of promises and give you a single promise back.
With Promise.all, you want all of your promises to succeed. If any of them fails, everything fails. Otherwise, you get an array of values.
With Promise.race, you want them to race each other and you only get the winner’s value. If any of them fail, they all still fail. Failure is bad.
- Promise.all resolves when all of its component promises have resolved.
It rejects if any of its component promises reject.
It resolves with an array of all of the values, but rejects with a single error.
- Promise.race resolves when any of its component promises resolve.
It also rejects if any of its component promises reject.
It resolves with a single value, and rejects with a single error.
Fun with promises
You now know everything that you need to know to create promises. You know how to create them, and how to execute things in serial or parallel.
Now you’re ready to learn about a couple interesting things you can do with promises.
Resolving a promise passes it on. This works whether that promise is currently pending, already resolved, or prematurely rejected.
You already know that when you call .then, it creates a new promise that is immediately resolved with .then’s callback’s return value. It’s a little like a Promise.resolve that waits for another promise.
So that means…
Your .then callback can return more promises that don’t execute until your last promise resolved, and you can write one handler at the very bottom that catches all the errors that might have happened up to that point.
You can even return another promise from .catch to return to regular, non-rejected programming.
Promises were supposed to help with this, right? How, exactly?
If you compare this code snippet with the last one, you’ll see that the last one took up more lines, but it’s definitely more sustainable. If you realize you missed a step, it’s just a matter of adding an extra .then statement instead of having to wrangle with your indentation scheme.
Or more commonly, if you wanted to add an extra action to the end of your callback tower, you had to widen your text editor even more and get ready to tack on a couple extra indentation layers. Callback based code is hard to use and scale.
So does that mean you have to rewrite all your code?
You don’t. It’s very easy to convert callback based functions into promise based ones. You can even maintain backward compatibility.
All you need to do is wrap your entire code block inside a promise, and plop in a resolve where you would place a callback.
If you want to maintain backward compatibility, add a .then to your promise with your callback in it. If you do so, make sure you return your original promise, and not the return value from .then.
Do you know why that is? I explained above.
With your callback handler wrapped in a promise, adding more actions to the end is easy and stress free.
If you made it this far, you should be all ready to go forth and make some promises! In fact, I started working with them without even knowing half of this stuff.
If you ever get lost or need to check a reference, I find Mozilla’s website to be really good at that kind of stuff these days!
The Promise object is used for asynchronous computations. A Promise represents a single asynchronous operation that…developer.mozilla.org
Wait wait wait! This .then thing is really annoying! I’m tired of wrapping stuff all the time!
await is coming.