Change language

012 Throwing Errors Manually

012 Throwing Errors Manually

So in this lecture, were gonna fix the request 404 error that we saw happening in the last lecture.

And so as we saw in the last video, the problem here is that during the fetch, there was a 404 error, which is because our API couldnt find any country with this name.

But still, even though there was obviously a big problem with this request, the fetch function still did not reject in this case, and by the way, many people, and that includes myself think that in this case, the promise should actually be rejected right away, but again, it just doesnt, and so we will have to do it manually.

So to see what happens here, lets go back to this first then handler here, which gets access to the response immediately.

So without even the data.

So here, Im adding back a block, and lets take a look at the response here.

And also, since we added back the block, we now need to return this explicitly.

So again, for now, we are just taking a look at the response object here.

And so here it is, and so right here, you can see that the Ok property is set to false.

And so the reason for that, is, of course, the status code 404.

Now, when the request goes well, and so thats whats gonna happen when I click here.

So then if we take a look at the response, Ok is true, and thats because status is 200.

And so 200 literally stands for Ok.

So we can now use the fact that this response has the Ok property set to false to basically reject the promise, or selves manually, now, right, so we can do that by creating a new error.

So we can say, if there is no response, dot Ok, or in other words, if response dot Ok is false, then we right, throw new error, and then here we can define an error message.

So lets write a very logical message here, which is country not found.

So this is the real error message that we want to see here, and of course, not this one here with cannot read property of undefined.

And here, we can then also take the status code, and display it as well.

So this 404, in this case, lets just wrap it here into parenthesis, and Ok.

So this is something that we never did before.

So lets analyze what happens here.

So we create the new error by using again, this constructor function, basically, and then we pass in a message, which is gonna be the error message, then we use the throw keyword here, which will immediately terminate the current function.

So just like return does it.

Now the effect of creating, and throwing an error in any of these then methods is that the promise will immediately reject.

So basically, the promise returned by this then handler here will be a rejected promise.

And that rejection will then propagate all the way down to the catch handler, which we already have set up here.

And so now, if we will try to reload this, and actually, lets do that.

So now this error message that we created here, so thats country not found 404.

So exactly this, this is exactly the rejection that we created here by creating this new error.

All right, so again, any error that happens in any of the callback functions here, so in any then handler, will immediately terminate that then handler and will propagate down to the catch method here.

And then in there, we handle that error, and so therefore, thats why we then see the error here displayed.

So that error dot message is exactly that message that we pass into the error here.

And in fact, the same is true for any other error.

So before we had this, the error that we saw was this one here, and thats because somewhere in the render country function, we are trying to read the flag from the data that we received, but the data that we received did not contain this flag.

And so therefore it created this error, and then that error caused the rejection of the promise, which was then one more time handled down here, okay.

So again, any error will cause any promise to reject, but here, we are simply creating our own error to basically reject the promise on purpose, so that we can then handle that error down here in the chain, so in this catch method, all right.

But now, you might be wondering, why should we even bother handle all these errors? Isnt that just a bunch of work and a waste of time? Well, first, handling these errors is the only way in which we can actually display an error message like this on the screen for the user, but even more important, its just a really bad practice to leave these rejected promises, hanging around without handling them.

So dont do that, always use catch, and if necessary, you can also use finally, okay.

And now, again, what if there was no error here in this promise? So if we got no problem in this one here, but then we get a problem in the second fetch.

So lets say that, we dont do this, and so we have a reasonable country, which is Portugal when we click on the button, but then here, lets say that the neighbor is not this one, but this country code, which Im sure does not exist.

And so now there is gonna be a rejection in this promise, right.

So we get another error here.

In this case, its a 400 error, which means something else, but in any case, the error is not handled.

So we now need to go ahead, and copy this code here, also into this then handler.

Lets actually do that, even though we know its a bad practice, and we need to fix this later.

Okay, and so now we get the error message that we want.

So again, country not found, and this time with the code 400.

But now, of course, we have all this duplicate code here.

So we shouldnt have this here.

And in fact, even all of this is kind of repetitive.

Its really, if you think about it the same code as this one.

And so now, I think that its a good time to actually create ourselves a really nice helper function.

And this helper function will wrap up the fetch the error handling, and also the conversion to JSON, because in my opinion, its really a bit cumbersome to having to do all these steps all the time.

So having the fetch, and then having to convert that response to JSON, and only then being able to handle it, right.

So instead, we will basically encapsulate all of this here into one nice function, so lets do that, and Im gonna call it getJSON.

So basically, because it gets data, and it immediately converts to JSON.

Now, what do we need here as parameters? Well, for sure, we need the URL, and so for now, thats okay, here.

So lets get, or actually, we can just write it.

So what we want here is fetch, and then the URL that we pass into the function, and then on that we want to call then, and then basically with all of this.

So lets grab it here.

And that, of course, we are missing the callback function itself here, so that should end somewhere here, and, well, apparently, it doesnt.

Maybe like this, and yes, thats correct.

All right, now in order to actually make this function her really generic, we do not want to hard code the error message, but instead, we want to pass the message in.

So lets say error message, and we can set a nice default value.

So lets say something went wrong, which again is very generic, and so here, inside of this, we then want the error message that we passed in, and along with response dot status.

Okay, and now all we need to do is to return all of this.

And so like this, this getJSON function will actually return a promise.

And so this is then just like any other promise that we can call here in our chain, and basically replace all of this.

So just so we can keep this code, Im gonna copy it.

And so you can then keep this code here, basically as a reference for when you need to study it again, okay.

But again, I will now go ahead and take everything that we just nicely encapsulated into our getJSON function, and simply replace this.

So getJSON, and then the URL is this one, and the error message is country not found, now, right.

And so now, we can take away all of this.

So this is already in our get JSON function, and so we dont need this.

All right, and now the same down here.

Instead of fetch, we can get JSON, and then we dont need this done here.

And again, the error message is country not found.

Okay, and so lets get rid of this, now, right.

So lets check here, and indeed, we get, again, country not found with code 400 because of this one.

So thats working great, but theres still one more thing that we need to do, which is to handle the fact that sometimes there might be no neighbor.

So right now, what were doing here when there is no neighbor, is to simply return, but as I mentioned before, that doesnt really do anything.

So let me just try here, a country that has no neighbors.

So lets say Australia, because that is an island, and so here again, we get cannot read property flag of undefined, and so that is happening, because it is trying to render a country that doesnt exist.

Okay, so again, its because of this neighbor, and just to make sure, to illustrate my point here, you see that the neighbor is indeed undefined.

And so what we want to do here is to simply just like before, throw a new error that will then get caught down here in our catch handler, right.

So throw new error, no neighbor, found, and thats a lot better.

So now, this is a real error message that actually makes sense to the user.

Of course, this could be all a bit better, but this is just a demonstration anyway, but I think that it nicely demonstrate how we can create a real error message that does actually make sense.

And again, that is super important for any user interface that youre building, because in web applications like this very small one, errors will happen, that is just guaranteed, and so your application needs to be ready, and needs to be prepared for that.

All right, so lets now quickly recap here.

And I think that the big takeaway from this lecture is that whenever we want to create some error that we want to handle down here, in the catch handler, all we need to do is to throw, and create a new error, just like we did here.

And of course, we can do that for multiple reasons.

So in this case, here, we did it simply because in the situation, no neighbor can be found.

And so that is a good reason to display an error message on the user interface, and since we do that down here in our error handler, the best way of doing that is to indeed throw an error.

And remember that this works, because throwing an error inside of this callback function of this then method will immediately reject this promise.

And so then that rejected promise will travel down the chain until it is eventually caught somewhere.

So again, in this case, it is right here in this catch handler.

So when working with real applications in the real world, really make sure to keep this technique in mind, because its really important.