Promises in JavaScript (es6/es2015). Creating and using promises with ECMAscript 2015 in your JavaScript application.
[00:01] In today's lesson, I want to go over promises with ES6 or ECMAScript 2015. Promises in ES6 are very similar to those of Angular's $q service, if you're familiar with that framework.
[00:14] First thing I want to do before we start explaining what promises is and how to use them is just build out a basic skeleton that we can add to throughout the video.
[00:23] To get started, we'll go ahead and create a new variable, which we'll just call "d," and we'll set that equal to a new Promise(). The callback inside of a promise takes two arguments, resolve and reject. You'll notice that we're using the ES6 arrow function syntax throughout this project.
[00:39] Promises can either be resolved or rejected. When you resolve a promise, the .then will fire, and when you reject a promise, the .catch will fire instead. Usually, inside of your promise, you have some sort of logic that decides whether you're going to reject or resolve the promise.
[00:55] Let's go ahead and build the basic if-else statement here. Inside the if statement, we'll go ahead and resolve the promise. We'll pass in a string of "Hello world." Inside the else statement, let's reject the promise, and we'll just pass in a string of, "No bueno."
[01:10] Now, because we're just evaluating the Boolean true inside this if statement, we know that our resolve is going to fire. To get an idea of what this is going to look like, let's go down to our d.then.
[01:19] The then method callback also takes an argument. This one we'll call "data." The value for data is the argument that is passed into the resolve method. In here, let's just go ahead and console.log, and we'll say success, and we'll print out our data.
[01:35] Alternatively, in the catch method, we also have a callback function as the argument, but here, what will be passed back is the information that's supplied into the reject method of our promise. Why don't we just go ahead and console.error, and here we'll say, "Error," and we'll spit out that error data that's supplied back to us.
[01:55] If we come back into our console and we run this logic, we'll notice that, "Success. Hello world," is returned to us, because that's what we have specified in the callback of our then method.
[02:04] If we go up to our promise and we change this true to false, we'll cause our reject to fire off, and, "No bueno," will be passed through instead. So, let's come back to our console and run it again. We notice we get our error, "No bueno."
[02:17] Promises are useful for a lot of things. Most importantly, they allow you to perform asynchronous operations in a synchronous-like manner.
[02:25] To get an idea of what this asynchronous behavior would look like, let's go ahead and create a timeout. Inside of the timeout, we'll create a function, and in this function, let's just put our if-else statement that we were using previously. Let's set a timeout here of two seconds.
[02:42] We still have our false being evaluated by the if statement, so after a two-second delay, we should see that our, "Error. No bueno," is passed into our console. Let's come back down here and run it again. We have a two-second delay where, "Error. No bueno," is returned to us.
[02:56] We can go ahead and change this to true, run it again, and this time we'll see that we get, "Success. Hello world," after our two-second delay.
[03:05] There's several different methods you can use when dealing with your .then and .catch callbacks. If you don't prefer to use the .catch method, you could then, instead, supply a second argument into the .then method, which will act as an error callback.
[03:18] In here, let's go ahead and pass in our error again as our parameter, and we'll just console.error. This time, we'll do a new message so that we can see that it's actually our second callback of the .then method which is being called.
[03:33] Let's go back up to our if statement, change true to false so we can make sure that our reject is what's fired. We'll come back down into our console. We'll run the code. Again, after our two-second delay, we'll see that the new error message, "No bueno," is returned to us.
[03:47] I prefer to use the .catch method for rejects and .then for resolve only. This ensures that I can always be certain that if I have a function inside of the then method, that it is my success callback, and I can put in the appropriate code.
.[04:00] Then and .catch can also be chained together. Let's go ahead and chain these two things together, run our code again, and we'll notice that we still get our error message.
[04:10] Alternatively, we can decide to chain several .thens together and have them called in succession. We'll notice now, if we change our if statement to true and run our code, the resolve will be called and both .thens will fire one after another. Let's come down and run our code.
[04:28] We see that we get success and success two. Notice that success two is undefined. This is because the data that's available in the callback of the second then is not what is originally passed into the resolve but rather what is returned from the original then method.
[04:42] To see a working example of this, let's go ahead and return a value from our first .then, which will then be passed into the second .then. If we come back to our console and run the code again, we'll notice that rather than undefined, we get foobar passed back to us.
[05:00] One more important thing to note is that whenever an error or exception is thrown within the promise, it will automatically trigger the .catch to call, regardless of when that error's thrown.
[05:09] To see a basic example of this, let's go ahead and throw a new error, run our code again, and we'll notice that this time our error is returned to us, even though we're evaluating true, which means our resolve should fire. This statement remains true, regardless of when the error's thrown throughout the promise.
[05:29] For example, if we come into our second then statement, we can go ahead and throw that error in the second .then, and we'll notice that the catch will also fire.
[05:38] Now, if we were to add that error to the first .then, then that second then would never fire, because it's going to go straight to the catch.
[05:45] Those are some basic examples of how to use promises with ES6 or ECMAScript 2015.
Very succinct! Nicely done.
I'm getting UnhandledPromiseRejectionWarning
when I run this simple code:
var d = new Promise((resolve, reject) => {
if (false) {
resolve('hello world');
} else {
reject('no bueno');
}
});
d.then((data) => console.log('success : ', data));
d.catch((error) => console.error('error : ', error));
The complete response is:
error : no bueno
(node:12883) UnhandledPromiseRejectionWarning: no bueno
(node:12883) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 2)
(node:12883) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
I don't see this error showing up on the video.
Seems like d.catch()
is being fired. I noticed that if comment out d.then()
, the warning message disappears.
I'm calling the script from the terminal like node foobar.js
.
What I'm doing wrong?
Tested with node v8.14, v10 and v11 under MacOS High Sierra.
Answer
It turns out that then()
returns a new promise that, in this case, gets resolved with the parent promise value, which is rejected. So the new promise rejection is not being catched. To catch it simple chain bothd methods: d.then().catch()
.
The audio on this lesson is almost non-existent!
I can't access to the code's lesson. The code tab just says "This bin needs a pro account
Embedding JS Bin under https is only available to bins created by users with a pro account.
If you own this bin, you should upgrade today to enable this feature on all your bins."