‫In this video, we're gonna learn
‫about debugging Node.JS because, let's face it,
‫there will always be some bugs in our code no matter
‫how careful we are.
‫And so it's good to have a tool to help us
‫with debugging our code.
‫Now this is not really about error handling with Express,
‫but I thought this was a good point in the course
‫to introduce you to a debugging tool
‫which we might then use throughout the rest of the course.
‫And there are different ways of debugging Node.JS code.
‫For example, we could use VS code for that.
‫But, actually, Google very recently released an amazing tool
‫which we can use to debug which is called NDB, all right?
‫So let's move over to our other terminal here
‫and then install NDB.
‫And NDB, which stands for Node debugger,
‫is actually just an NPM package.
‫So NPM install NDB.
‫All right, and you should then install it
‫as a global package, all right?
‫And if you're on a Mac, you might need global permissions.
‫So just write sudo here in front.
‫Or if you're not at all able to install it globally,
‫you can always just install it locally
‫as a death dependency.
‫So just like this, all right?
‫Anyway, please go ahead and install this tool now.
‫I'm not going to do it
‫because it can be quite a heavy download, and
‫that takes a bit too long now.
‫Anyway, as soon as you have the tool installed,
‫then let's head over to package.jason
‫and add a new script here, all right?
‫And I'm gonna call that one debug.
‫Okay?
‫And so the command that we want to run here
‫is simply NDB, so the note debugger
‫and then again our entry point,
‫So, server.js
‫Okay?
‫And now this is gonna work no matter if you installed
‫NDB locally or globally.
‫All right, so let's now run the script.
‫And in order for this to work
‫we actually need to finish this process
‫because it's basically gonna start
‫the server as well and so it will then
‫try to do it on the same port
‫and that's of course not gonna work.
‫So we need to finish the one that's currently running
‫and then from here we can run NPM
‫run
‫debug
‫All right, and so now
‫a new Chrome window should open
‫so what's called a headless Chrome,
‫but it's not a real Chrome.
‫So you will see the Chrome icon down here
‫and also here in the menu bar
‫but really this is just the note debugger.
‫So what do we have here?
‫Well on the left side, we have our complete file system.
‫We also have access to our NPM scripts here
‫which we can actually run from here.
‫We also have a console
‫and so here we have our usual outputs with the app running
‫and the database connection
‫and we also have the performance and memory tabs,
‫which we're not gonna use.
‫All right, now if you're familiar
‫with the general debugging process
‫then all of this gonna be kinda familiar to you.
‫All right, but if not don't worry
‫I will show you a couple of techniques
‫throughout this video.
‫All right, anyway let's now open up our server.js.
‫And one thing that's really amazing
‫is that we can actually edit our files in here,
‫so right in this debugger.
‫So, for example let's say that we find a bug
‫and we then want to fix it right away.
‫We can do that right here in the debugger
‫and it will then update the original code.
‫So just to test it,
‫let's just add a comment down here.
‫So, test then hit command or control s to save
‫and then when we go back to our code
‫and open up server.js
‫there you will see that the comment is actually here.
‫Okay?
‫And if we now delete it from here,
‫give it a save,
‫and back to the debugger,
‫then it is gonna be gone from here as well.
‫Okay, but now about the debugging itself.
‫I would say that the fundamental aspect
‫of the debugging is to set break points.
‫So break points are basically points in our code
‫that we can define here in the debugger,
‫where our code will then stop running.
‫It will basically freeze in time
‫and we can then take a look at all our variables.
‫Okay, so that will then be extremely useful
‫to find some bugs.
‫Now, right now there's not any bug in here,
‫but let's still add a break point.
‫And I'm going to add that break point here in this line 21.
‫So I click here on this line
‫and then you see this green marker, okay?
‫And so that means that the code will stop at this point
‫when we execute it, okay?
‫And you actually can see it here on the right side
‫on the break points tab here as well.
‫Now, our application is actually
‫already running at this point
‫and basically waiting requests to come in.
‫And so what we need to do here
‫is to right click and then click on run this script.
‫Okay, and so that will then basically
‫run the script here again.
‫All right?
‫And so here we go.
‫So you see here on the right side,
‫that that it says paused on break point
‫and so all the code that is above this break point here
‫has already executed at this point.
‫And so we can now take a look at the variables.
‫For example, we can hover this port variable
‫and we see that it's set to 3,000.
‫And also actually hit this place here
‫in the code here, all right.
‫And then the third way of seeing it
‫is here on the right side.
‫So we have a couple of basically tabs here
‫so node processes, the watch, the call stack,
‫which is not really important for now.
‫The scope, and so the scope is where all our
‫variables are, okay?
‫And so here again, you have the port set to 3,000.
‫Okay, and here you also can see
‫the five variables that we have access to
‫in all modules.
‫Remember that from the models lecture?
‫So we have the directory name,
‫we have the file name, we have the require function,
‫we have module, and we have export.
‫So remember, these are the five variables
‫that are available in each and every module.
‫And actually when we execute a code like this
‫in the debugger, we can see that our entire code
‫is in fact wrapped into this function.
‫Right?
‫So this wrapper function that gives us access
‫to these five variables.
‫All right, next I also want to take a look at
‫our app variable, so basically the Express application
‫that we export from app.js, remember that.
‫And here is really a ton of stuff
‫but what I find interesting
‫is to take a look at this router here.
‫Okay, and so in router we then have stack.
‫Okay, and so let's open this up a little bit
‫and so this stack here is basically
‫the middleware stack that we have in our application.
‫Okay, for example we have our jsonParser here,
‫we have the code that serves the static files.
‫Take a look at that here in app.js
‫so this express.static.
‫We also have the logger here
‫which comes here from using Morgan.
‫Then you have these next two middleware functions,
‫so these two here,
‫which are anonymous, so this one and this one
‫and maybe we can take a look at them.
‫But not really.
‫Okay, it doesn't matter.
‫So this is really just for curiosity
‫and showing you that we actually
‫can take a look at our middleware stack, okay?
‫Then finally we have our two routers.
‫Okay?
‫So, we have the router, and you see here actually
‫the route for which it applies.
‫So api/v1/tours right and so I find this really interesting.
‫Of course we still have the users here as well.
‫And so with this really can take a look at how the
‫Express application works behind the scenes.
‫Okay?
‫So let's close up all of this.
‫And the other thing that I wanted to show you
‫is here in the global variables
‫because here we have the process variable
‫or at least we should have it somewhere here.
‫Yeah, so indeed here it is.
‫So here we have the process variable
‫that is remember, available everywhere.
‫And so that's why it's called here a global variable.
‫Then in there we have process.env
‫and to remember that this where
‫all our environment variables are stored.
‫And so indeed here we have our database string,
‫we have the local database, the password,
‫and really all the other environment variables
‫that we defined in our config.n file.
‫All right?
‫So really interesting stuff that we can take a look at here.
‫But now let's continue with our debugging.
‫Okay?
‫So we stopped the code, we froze it in time
‫here at this point, so at line 21.
‫Okay, and so now we can click here on this button,
‫in order to actually continue to running the code.
‫And since we have no more break points,
‫the code will then break no more,
‫and basically finish running.
‫So let's do that.
‫And so now our application is really running.
‫Let's take a look at that.
‫In Console, okay?
‫So app running on port 3,000
‫and DB connection successful, of course.
‫What's happened here?
‫Now, all right,
‫so let's now quickly do a request here.
‫So simply one for /tours
‫and now we have all this junk here
‫and I'm gonna take care of that in a second.
‫All right, and if you now come back to our Console here
‫then of course we have all the code that we had before.
‫Hello from the middleware and then
‫how the long query actually took.
‫All right, and now before we do anything else
‫let's actually get rid of these junk tours.
‫So I'm gonna reload it here,
‫and I guess it will be somewhere here at the end.
‫So, test whatever here.
‫So let's get rid of it.
‫This is the secret tour and I actually want to keep it here.
‫But everything from here on we no longer want.
‫And so
‫so yeah, so now we're back to having just 10 tours,
‫just as before.
‫Anyway let's now actually set a break point
‫in the function that handles this route.
‫Okay, and so we come to our controllers folder
‫and there we have the tour controller.
‫Okay?
‫And then the handler function is this get all tours.
‫So for now all I wanted to do
‫is to just set a break point here
‫so that we can take a look at what these variables
‫look like after the query is already done.
‫So this code here will get our tours
‫and we will then stop the code
‫basically before actually sending it as a response.
‫Okay, and so all we need to do is to actually do the request
‫because that will then trigger that function.
‫Right?
‫And so since we have a break point, we automatically move
‫back to this window here, and to the point
‫where the code has stopped.
‫So, what kind of variables do we have here?
‫So you see that we have the request and a response,
‫and we also have the features variable,
‫and the tours, of course.
‫So let's first take a look at the request.
‫And here again, you see that we have all kinds
‫of stuff really.
‫So we have, baseurl, we have the method,
‫we have for example, request.query,
‫which right now is empty because we didn't pass
‫any query string,
‫but you see that it's really already here.
‫Okay, and so you start seeing now how handy
‫this can be in order to debug our code.
‫So basically to freeze our code in time instead of
‫having to do all these console.logs that we used to do
‫up until this point.
‫So usually when we wanted to take a look at
‫the query for example, we would do a bunch of console.logs
‫and use that to figure out a bug in case that something
‫was not working.
‫Right, but now we have this amazing tool
‫which can help us avoid all these console.logs
‫for example.
‫Then we also have the response of course.
‫And again you see all of these properties and methods
‫that are on there, and they are not really interesting
‫for us now.
‫What I wanted to show you is of course at this point
‫we already have the tours, okay?
‫So we have nine tours, so let's take a look at them.
‫And it looks kind of weird here, so in order to get access
‫to the actual values, we need to click here, okay,
‫so that's a bit weird.
‫But it works of course.
‫And so you see that in fact our tours are already here
‫and of course the features as well.
‫So you see here that the features are an instance of
‫the API features class just as we defined it.
‫And in there we have the query and the query string.
‫Great, so this is how we take a look at all the variables.
‫And this is how the most important parts of
‫the debugger work.
‫Now in order to learn a bit about the debugging process
‫itself, let's introduce a very small bug into our code,
‫and then take a look at how we can use these tools
‫that we have here to basically take a deeper look
‫at our code.
‫So I'm not gonna resume the skipped execution
‫in order to run basically the rest of the code, okay?
‫So that should be done now.
‫So now here we have all response.
‫So you see that it took all this time here,
‫so three minutes and 29 seconds,
‫but that's just because we paused the execution
‫for so long.
‫Okay.
‫Now let's come to our code here.
‫Let's close what we no longer need.
‫So actually in our API features file,
‫I want to introduce a small bug here in the limit fields.
‫So let's say that we were trying to implement
‫this method here, but instead of joining with a space here,
‫we forgot to put it here.
‫And so let's just say that we joined without any space,
‫and so this would then give us a weird result, right?
‫So let's actually test it out.
‫So let's say
‫fields and that we wanted only the name
‫and the duration, right?
‫Now before I can actually send that request,
‫let's remove the breakpoint here.
‫Okay?
‫Sent the request, and now we actually do not get
‫the name and the duration.
‫So let's pretend that is our bug now
‫and we're now trying to figure out why this is not working.
‫Okay?
‫So let's go to our debugger.
‫And we know that the error must probably be
‫somewhere in our limit fields method.
‫And so let's basically stop the code from executing
‫at this point, okay?
‫Because this is where this method will actually be called
‫and so from here we can enter that function
‫for that method.
‫Okay?
‫So then let's fire off that request now,
‫and so now we go back to our debugger automatically.
‫So at this point this line and this line and this line
‫of code have already executed, and so let's now use
‫the step tool, okay?
‫What step will do is that it will basically execute
‫the next line of code.
‫And in this case that will be inside of
‫the limit fields method.
‫So step, and it will then move right into that function.
‫Okay so let's take a look at what we have here.
‫For example this .query string is name comma duration,
‫so that is correct, right?
‫Okay so let's step to the next line.
‫All right and so this is where this operation
‫is actually happening.
‫Then next up.
‫Let's take a look at our variables here.
‫And so here we now see field, and so here we have our bug.
‫Okay?
‫So the problem is, of course, that we have no space
‫between name and duration.
‫And so that's why it's not working.
‫So fields is of course defined here, and so like this
‫we can find our bug and correct it right away.
‫So remember that the added step we do here
‫are reflected immediately in the code.
‫So give it a save,
‫and then it will do it again.
‫So I can keep stepping.
‫And so now fields is correct.
‫So name space duration.
‫Then the next line of code.
‫And now we enter into the select method on the query.
‫But we're not interested in that at all,
‫so we can say "step out of current function."
‫Okay?
‫So that select that we just thought was running
‫this function here, okay?
‫But of course we were not interested in that
‫so we just quit it and moved on to the next line.
‫So now we have return this,
‫next line, and again.
‫So now we're back to where we were but in the next line.
‫So let's keep doing that.
‫So now we're into page eight,
‫but we're not really interested in this one,
‫and so let's again step out of the current function.
‫And now we're here at the tours definition.
‫Which at this point is not yet done.
‫And so let's again say step.
‫And so now at this point our tours should be defined.
‫All right so we have our nine tours over here.
‫Let's take a look at them,
‫and here they are.
‫And actually they have all the data,
‫so not just the one we defined but in fact,
‫actually it doesn't.
‫So we really only have the name and duration,
‫so duration, name, and all the other ones
‫are undefined.
‫So that's just because we limited a query to only
‫these two fields, remember?
‫Now what I also wanted to show you is here in the features,
‫we can take a look at our query and here we have
‫the fields property for example where we see duration
‫set to one and name set to one.
‫And so that's exactly the two names that we selected.
‫We also have these options here,
‫which is at this point set to create it minus one.
‫And so that's coming from here.
‫So this here.
‫So basically what this method here, this sort method
‫is gonna do is that it will add this sort property here
‫to these options, all right?
‫And then we also have limit and skip which of course
‫come here from page eight.
‫Okay?
‫So I thought that this also kind of interesting
‫and yeah, so our code is now actually fixed and let's keep
‫running this.
‫And so we now should have our correct result.
‫Now here it says we could not get any response,
‫and that's because we took too long fixing our code.
‫So we got an error connecting.
‫But if we now send it again,
‫and now we do it quicker.
‫Or actually we could remove our breakpoint entirely.
‫So let's keep it running,
‫let's go back and now indeed we get the duration
‫and the name as well.
‫So that's because we just fixed our code
‫using the NDB debugger.
‫So great.
‫That's a really amazing and helpful tool
‫that we're gonna keep using throughout the rest
‫of the course.
‫Maybe not always, sometimes it's quicker to just
‫throw in a console out log.
‫But really, in some more complicated cases,
‫I like to use this kind of tool.