JavaScript: From First Steps to Professional

Browser Debugger

Anjana Vakil

Anjana Vakil

Software Engineer & Educator
JavaScript: From First Steps to Professional

Check out a free preview of the full JavaScript: From First Steps to Professional course

The "Browser Debugger" Lesson is part of the full, JavaScript: From First Steps to Professional course featured in this preview video. Here's what you'd learn in this lesson:

Anjana demonstrates using the browser's built-in debugger, including showing multiple ways of setting breakpoints to assist in finding errors.


Transcript from the "Browser Debugger" Lesson

>> Another thing that we can do is use the browser's built in debugger. So we have in our dev tools here, we've seen so far we have our inspector, where we can look at our HTML and our CSS. We have our console where we can talk to JavaScript as we've been seeing.

And we have a tab called debugger. What this does is, it is really really handy feature built into most browsers like Firefox and Chrome. Both have really great kind of developer workflows for this. And what it does is, it lets us see all of the code that our pages running, in this case it's coming from this HTML file.

But if we were working with a bunch of different modules, we might be seeing those different.js files in here. And it shows us the source code that we're running through when we run this file. And so here for example, I'm trying to load my doggo fetch page, and something is going wrong, I'm not getting my doggo, my doggo is not fetching.

So let's try to find out what is going on. So, one thing we can do in our code is write a special keyword, debugger. And again, this is maybe a temporary thing. But what we can do is if we insert a debugger statement, which is just the word debugger and a semicolon usually.

What that does is it creates what we call a breakpoint or a pause in our JavaScript program. And if we are running our code in our browser with the debugger open, JavaScript will pause there. And let us look around and see what's going on. So let's try to add one in our code, something is going wrong.

So let's go to our loadData function, our loadQuizData function. Now we know that this line is working because I see the words fetching doggo in my webpage, so that happened. So something is going wrong after that. So why don't we just put a little debugger statement right here, I'm gonna save.

Now I'm going to go back to my, I'm loading this local file in my browser, I'm going to refresh. And now we see this little message paused on debugger statement. And in my debugger, I see this big pause here, and I see that we are now at this line of code 191 in our case, where I had that debugger statement.

Okay, now there's a lot going on here, so let's take a look. One of the things that we can see here are, there's this, and it's slightly different in different browsers. So right now I'm in Firefox, if you're in Chrome it's gonna look slightly different. But the browsers all have kind of concepts of being able to investigate what's happening in our program.

So, one thing we have here is what's called the function call stack. Not getting into a ton of details about this, but this is essentially JavaScript's notion of when I'm calling a function within a function within a function. JavaScript stacks them up and sort of says all right, right now we are in our module, in our HTML module.

And we are inside our loadQuizData function, that is the function that's currently being called. So that's what we say is at the top of the call stack. Now we also have, we have a whole bunch of other stuff going on. But one thing we have is, here in Firefox we can see these, the scopes that are in play right now.

So which variables are in play? And we have in this case, we're inside our loadQuizData function. So we have our local function scope with various values that we're gonna have inside this function. So for example, it already knows because it read ahead in our code a little bit, it already knows that we're about to declare some new variables like doggo image, URL, and correct breed.

But we haven't declared or assigned values to them yet, so it shows them that they're uninitialized. But as we're running our code, we can see the different values of things here. So let's go ahead, what we're gonna do now we're paused, but what we wanna do is what's called step through our program.

So we wanna take it real slow, and go one step at a time through our code and find out what JavaScript is doing. You'll notice in your debugger some buttons, and they're gonna look slightly different in different browsers that allow you to control the movements of the debugger through your code.

So one of them is going to be like a play button that just says, hey, keep trying to run. And that's going to run until the next breakpoint or the next debugger statement that we've set. And another one that we're going to have is to step over. Let's see if this shows up.

It's called step over, meaning step into the next line of code and try to run it. So let me move this down so we can see a little bit more of our code here. Okay, so if we step over this debugger line. Now we're gonna go to the next line and JavaScript is going to do the next thing.

And the next thing that it has to do is await this fetch message call. And so nothing has really changed in our scopes so far. Another option that we have in our stepping through our debugger code when we're about to call a function like fetchMessage, is we can do what's called stepping into the function.

So this is where we're not just going to call the function, we're actually going to break it down even further than that. And we're gonna step into the fetchMessage function code. So if I now press Step in, it's going to advance JavaScript into the next function call. So let me click that.

Now we've jumped into our fetchMessage function. And we haven't really done anything yet, but if we look in our scopes, we can see that we are now in a new scope. Now we're in the fetchMessage function scope, and that's gonna have some other values here. And what we're trying to do is understand what is going wrong, and so now we can see that for example inside of our fetchMessage we had this parameter URL.

And URL now has a value inside of our function scope, inside of our fetchMessage scope of this string. And if anybody has a really good eye, maybe they can spot something. But for now, let's just say this is gonna give us some information about what fetchMessage is seeing that might be useful.

So now the next thing JavaScript is gonna do is try to call that fetch built in function. We don't really need to step into that function because that's gonna be a lot of complicated stuff, and we didn't write that code. So for now, we can pretty much trust fetch is gonna do its job.

But we can do is step over this function, this next line of code or this next thing that JavaScript is gonna do, which we want it to try to run this line const response equals await fetch. Question.
>> Name of the breed is missing.
>> So the name of the breed is missing.

So actually we were looking at a few different endpoints on this dog API. Let's look at the dog CEO API documentation real quick. It's a fun one for projects and for testing stuff out. So we had, for example, earlier been looking at this kind of url, right? Like breed slash hound slash images or in our case we were looking for, wow, that's a lot of images.

Okay, okay, all right. [LAUGH] We were looking for sub breeds for example earlier. So, we had used this endpoint of slash breed slash hound slash list, where we did need to include the name of the breed. But there's actually another endpoint which is what we're using in our random guest the dog page here which is our game, which is this endpoint to fetch a single random image.

And that was what was returning back a JSON object with the message property being some specific image URL. Which we can then use as the source of the image element that we're loading into our page. So this is the endpoint that we're trying to hit. Does anybody notice anything that's going on here.

So the endpoint that we need to hit is dog dot ceo slash api slash breeds slash image slash random. If we go back into our debugger, we can look at the URL value here. And we can even, if we go into our console, right now we're paused in our JavaScript.

We're paused in the middle, and we're in the middle of this fetch message function. So we can access anything in that function scope, even at the console. Now because we're paused, we're in matrix bullet time state of JavaScript here, so we can stop and look around. And so if anybody notices something about this URL that we're trying to hit.

We'll call it out in a second. But let's just double check what's happening here, why this page isn't, what's happening where we're hitting an error in this page. So what we're gonna do is we're just gonna keep trying to run our code. So I'm going to use step over to try to run the next line of code.

And, a little error thing popped up here, and if I go to my console, I see that I get a 404 not found error. Which yeah, we can check again on our httpcat404, means, a resource was not found. You've probably run into this before when you find it, a lot of websites have a 404 page, that says, no I couldn't find your web page.

So this is that error, which means there is nothing at the URL that we tried to fetch from. And so if we check this string, so the URL string that we're trying to look for is dog dot ceo slash api slash breeds slash image slash rando, instead of what the API documentation says we should be getting, which is slash random.

So somehow I accidentally deleted a M from my URL here, and so there's nothing at that endpoint. That endpoint doesn't exist in this API, there is no resource there. So we're getting this 404 error. Now this is just one example, and we actually probably could have seen that error pop up in the console before anyway, we had run the debugger.

But just to show you that it could have been something else, it could have been perhaps I had an undefined somewhere that I can see by looking at my scopes and seeing what is coming back there. And so we can set these breakpoints. One way that we can do it is with that debugger statement.

Another way that we can do it is even if we don't wanna edit our code right in our JavaScript. So let's go back and take out our debugger statement. Take it back out. So now if I run the page again, if I refresh Well, if I finish running this page and then refresh, it didn't pause because I have no debugger statement.

I still got my error. So I could see in the console that there was this network error of a 404 response. But I could also set a breakpoint manually in the debugger tools by clicking on the number of a line of code. And again, each browser has a slightly different interface, but they all pretty much work this way, that you can click on the number for a line of code.

So, if I wanted to do the equivalent thing of my the debugger statement that I set in between these lines here. I can do that in the browser by clicking on this line here, and we'll see it enter it's inserted it's a little pause point. So, now If I rerun the page, it's going to pause on that break point.

So, we have two ways of setting a break point, we can use the debugger statement in our code or we can set it by clicking on the line in our debugger. Question?
>> Sorry if you already fixed this but they're saying spelling incorrectly spelled the word random.
>> Exactly.

>> Yeah.
>> Yeah so this turns out to be the problem here which we can see by looking at that. And here let's we can just do it again just to show that it works the same even without our debugger statement. Now we're paused in the same place that we were paused before, we're just using it by clicking into the dev tools in the debugger.

We clicked on a line of code to set a breakpoint instead of using the debugger statement, they do the same thing. So now I can again step over and see that. Sorry, let me reload, I actually wanted to step into, I can step into fetchMessage. And in my scope of fetchMessage, I can see that URL ends in rando, which I could also check by asking for URL in the console.

Because again, we're paused inside the function, so we have access to the function scope. And I see oops, I forgot an M. So now I can go back to my file and put the M where it's supposed to be and save. And now, if I reload the page Sorry, so right now I'm paused, so JavaScript isn't gonna do anything.

I can resume, I can play through to the rest of my code by pressing the play button here. So now I'm gonna reload the page. Now that I've made my fix, we're still paused on this break point because I didn't remove the break point yet. But now, if I step in to my fetchMessage function, I see that the URL now inside of my fetchMessage scope.

Just gotta move this up, so we can see a little better, inside of my fetchMessage scope I now see that the URL has that M on it. Okay, so we should be looking better. Let's try, let's step over this fetch and make sure that we get back. So we were stepping through our function, we had finally stepped out of the fetchMessage function.

And so we stepped through, now we see that the doggo image URL was set to an actual JPEG image URL, which is what we expected. Great. So now feeling pretty confident that the problem was solved, and we can continue with the rest of our program. And so what is called resume the execution of the program, I can tell JavaScript, okay, we're done pausing, we're done stepping, we can just go ahead and keep running.

And in fact, I don't need my breakpoint anymore. So what I can do is remove my breakpoint, which I had set by clicking on this line number. I can click on the line number again to remove the breakpoint so that the next time I reload the page, it won't pause there.

And I can hit this Play button to resume loading the page, and it runs through the rest of the script. And I get my adorable little doggo which we saw [LAUGH] was an. So this is just a really to let you know that the debugger is there to be your friend, to help you figure out what is going on in your program which is especially useful when we're working in modules.

And we can't see those global scope variables because the module has its own scope. If we pause in the execution with the debugger breakpoint, we can examine the scope and see what's going on. And so this can be a useful tool. But you can also console a log from within a function to find out what is going on, and what the values of things are.

Make sure you've got the right strings that you thought you had, etc.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now