API Design in Node.js (using Express & Mongo) Exercise 3 Solution
This course has been updated! We now recommend you take the API Design in Node.js, v4 course.
Transcript from the "Exercise 3 Solution" Lesson
>> Speaker 1: For app.param, again, this is going to, because, first we actually registered app.param, before we registered these routes. Which is great. That's, adding it to the stack earlier. If we put this below the routes, then it wouldn't work, regardless. So we add it before the routes. And then we have, it's looking for the parameter of the name of id.
[00:00:31] And then it passed that value as the fourth argument here, right. And then what we do is we just do what we did before. We just find the line with that id. If it's the line, attach it to direct.line then call next. If not then just nothing. Just send back to the client like that's not a real id.
[00:00:50] So you set the status code to something else, but yeah. Just respond back to the client don't even go next.
>> Speaker 1: The next one was create an error handler, so this is actually wrong cuz it needs to be down here. Boom. So error handlers just like we did last time.
[00:01:17] It's a middleware function that takes in that required four arguments with the error of the first one. And then just sends back an error here.
>> Speaker 2: Scott, what is it sending back on line 71 there with the error logic?
>> Speaker 1: That's actually misspelled. Thank you, I didn't notice that.
[00:01:33] THat would send back a syntax error. [LAUGH] Well actually that would throw a syntax error on the server, it wouldn't send back anything.
>> Speaker 2: I never get that either, i didnt know how to.
>> Speaker 1: Yeah I didnt hit it because it was up here. I didnt move it down.
[00:01:47] I should hit it now. So if you move it down, throw an error at one of your routes. Maybe throw an error at param. As long as you pass an error into next. It will hit this.
>> Speaker 1: If you just throw an error it won't hit it. It will just throw an error.
>> Speaker 2: And can you explain again why it matters if you move that down?
>> Speaker 1: Yep. So imagine this, let me show you this. So I'm gonna make an array of middleware. And I'm just gonna call it cbs, for call backs. And what happens is, when we say app.use, we're registering callbacks inside this array.
[00:02:29] So the first one we do is we put Morgan in there, because that's the first app.use. The second one is express.static. The next one is the body parser, I'm just gonna put bp, the next one is the other body parser, I'm just gonna put bp, and then app.param, just gonna put param.
[00:02:54] And then after that we have all these routes here which have specific verbs on them. So they're not on the same level, they're more like siblings. So I'm just going to put routes here because they're all inside of here. So the get, the post, the delete the put, they're all inside another array, they're like siblings they're on the same level.
[00:03:16] So Morgan's first, this is second, this is third, this is fourth, this is fifth. Any one of these can be sixth. And then the error messaging is down here. That's the seventh one in the stack, so then the error handling. Now, when we're inside of one of these routes, or even inside a param if we called next on one of these with error in it, it'll go here.
>> Speaker 2: Whereas, how was it before when it was up?
>> Speaker 1: It was up like here, so if we were to call next on one of these routes there's nothing out there, it just wouldn't do anything. There is no next. It would just hang probably, I don't know what express does in that scenario.
>> Speaker 2: And that's because you're using next to kind of funnel the error.
>> Speaker 1: Yes.
>> Speaker 2: But if we did something like new error it would get caught anywhere it showed up in that stack.
>> Speaker 1: Anywhere, if you just come in here and are like throw new error, this works the same way it works in every java script scenario.
[00:04:25] It will stop the execution of java script and throw an error. It will stop everything. But, we're not handling the error. We just don't want to throw an error, because now I mean this is bad on a server, on the client this is okay, but on the server this is bad because now the entire server is gonna stop and shut down.
[00:04:42] So now everybody that's connected to your server is do ne, because one error threw. So you don't wanna just throw this error out willy nilly like this, you wanna capture it in a place and then maybe if you have a very well built API you are probably logging your errors or sending them off to some error report service, and having to do that every single time.
[00:05:00] If we were doing some long calculation here like a DB query, we'll get into databases but if we did like a DB query on all these functions here, every DB query has a chance of throwing an error. We'd have to check for the error, do our logging, do our error reporting in every single one of these functions.
[00:05:17] Or we can say if an error go to next. And then do that one time here.
>> Speaker 1: Let me make a better example. So let's say we have var logg.
>> Speaker 1: Error. It's a function.
>> Speaker 1: My God, come here. So loggError's a function. It doesn't do anything, just assume that's it's some function we use to log our errors.
[00:05:49] What I'm saying is right now this is trivial we're not really doing anything in our calculations that might throw errors, but just in case we do throw errors like in database queries or whatever like I don't know let's say db.query this is all hypothetical but db.query and it may give back an error, it may give back the result.
[00:06:11] What I'm saying is, instead of having to do something like this. If, you know error, you know, what was it, LoggError?
>> Speaker 1: On every single one, right? Then we have to bring log error into every single file, and every other single file cuz we're gonna start making routes in other files.
[00:06:38] We have to make sure that we bring this everywhere we go. Everywhere we're going to expect an error, we have to bring this with us. So it's required everywhere we go. Instead of doing that, we can just say, hit error, next error and then come down here and say yeah, log the error.
>> Speaker 1: And then now because we were inside one of these routes, and we call it next with an error in it, it's going to go here.
>> Speaker 2: Okay, what if there was something in-between line 27 and 28.
>> Speaker 1: Good question, so if there was something else here, as long as that something else is not an error handler middleware, it will skip it.
[00:07:21] Right and we know it's a error handler in the middleware cuz it's got these four args. So if I put like another error handler in the middleware here what you can do as many error handling middlewares as you want with error response or I'm sorry, request response next.
[00:07:40] It'll run this one first. And then inside of here I can do some, maybe you might have like one error middleware that logs it, and then it'll call it next, then it will send out to another middleware that will send it out to a server somewhere, and then you call next, and you have another third error handling middleware that responds to the client.
[00:07:56] So yeah, as many middleware as you want, and just keep calling next, it will keep going. But you just have to make sure you pass in an error object to the next to trigger the error middleware. For instance, this one might do something and if i want it to go to the one below it.
[00:08:11] I just need to make sure I called next and pass in error and then it'll go to the one below it. If I just called next without the error it won't go to the one below, it just won't, here's nothing out there then. Yep.
>> Speaker 3: I think they're discussing like on line 40.
>> Speaker 3: Let's see Rob was asking, why is he using res.send instead of using next.error.req response?
>> Speaker 1: Let me back track some, make sure I'm on the right line, hold on.
>> Speaker 3: Yeah, that's the only thing I was.
>> Speaker 1: Okay. Line 40, yeah, my line numbers are messed up.
[00:08:55] Do you know?
>> Speaker 3: So yeah, maybe it's now if you were doing a response.send.
>> Speaker 1: Over here?
>> Speaker 3: I think maybe on 30, yeah.
>> Speaker 1: So why am I doing a response.send instead of what?
>> Speaker 3: Instead of a next error request response.
>> Speaker 1: Yeah, so like I said you probably don't want to.
[00:09:16] I was saying, you'd probably want to set a different status code here, or do an error. That's definitely more appropriate. I just did this just to end the request response cycle. Just to be sure that nothing's gonna happen. But yeah. In a real API, you definitely want to either throw an error, or send the appropriate response header for resource not available.
[00:09:36] Which is, I forgot what status code that is. Four something. But yeah you want to do that instead. So yeah you could do that in the next error. You could say, yeah you know, instead of that I'm just gonna say next, and like you know, a new error.
>> Speaker 1: Yeah, you could do that. The important thing to remember is that you just need to make sure you end the cycle. But yeah in this situation I would either just set the status to the appropriate header and send back a response or I would call next with an error but I wouldn't just do rest.send.
>> Speaker 1: Good question.
>> Speaker 1: Okay so that's the param, that's the error handler and then there was one more thing, yeah that was this one the update id. So the update id, it's a middleware function, all it does is it, first I'm checking to see if they didn't already put an id property on there.
[00:10:25] If they didn't, I'll increment it and then I'll just attach it to the body and then call next, that's it. I guess you didn't have to do the if check, I guess if you just, yeah, guess you really didn't have to do if check. This will override the check that I had last time.
[00:10:42] So yeah, you could get rid of the if and it'll be better, probably. But, the important thing is, I'm just adding an ID property to req.body and then calling next. So, what happens is now when you do a, where is that callback, right here. If you do a post request to lions, first it's gonna call update ID which then will grab the req.body which is the object that the client sent to us, attach an ID property to it, and then call next.
[00:11:14] Which will come back down here and then run this function and now this lion property has an ID property on it which is is reg.body, so I can just push it in there and send it back.