Charles' Profile picture
Hi, I'm Charles Szilagyi, full-stack engineer, founder, mentor. I'm using software to make things better without making them worse in London, UK.

Debug anything: Navigating with steps

06 April 2020
3 min read

It's important to learn how to navigate around the code you're inspecting. Going through each line of the codebase would be tedious and unnecessary. Debuggers offer handy ways of looking into what matters and jump out of code blocks that don't. Let's see how to step into, over and out of functions while debugging!

In the previous episode we've started exploring the VS Code debugger. We've added breakpoints to our tiny codebase and glanced at the local state.

This time we'll learn how to follow the code execution line by line and how to jump in and out of function calls.

Get the code

First, let's change our single-function server into something more complex. We'll add two extra functions: one to get the name from the request and another to generate the greeting.

You can copy-paste this code as index.js in an empty folder.

const http = require('http');
const url = require('url');

const hostname = '127.0.0.1';
const port = 3456;
const serverUrl = `http://${hostname}:${port}`

const getNameFromReq = (req) => {
  const {name} = url.parse(req.url, true).query;

  return name
}

const getGreeting = (name) => {
  const greeting = `Hello, ${name}!`

  return greeting
}

const server = http.createServer((req, res) => {
  const name = getNameFromReq(req)
  const greeting = getGreeting(name)

  res.statusCode = 200;
  res.setHeader('Content-Type', 'text/plain');
  res.end(`${greeting}\n`);
});

server.listen(port, hostname, () => {
  console.log(`Server running at ${serverUrl}`);
});

Source code opened in VS Code

The code for the series is available at https://github.com/thekarel/debug-anything

Start the debugger

Let's start the debugger: use the debug toolbar or press F5 and select Node.js:

Starting the debugger

You should be able to visit http://127.0.0.1:3456/?name=Coco as usual and see a greeting.

You can also use curl http://127.0.0.1:3456\?name\=Coco if you're that kind of person

Ok, so far we've only established the server is up and running - let's add a breakpoint. Without a breakpoint, the debugger wouldn't start:

Adding a breakpoint

You should have a breakpoint now on line 21:

const name = getNameFromReq(req)

Step by Step

Fire off a request again to http://127.0.0.1:3456/?name=Coco - the debugger will kick in and stop code execution on line 21:

Debugger started

Wonderful. Let's focus on the debug toolbar now:

The debugger toolbar

First of all: names. The buttons from left to right are the following (with the default VS Code shortcut):

  • Continue / Pause F5
  • Step Over F10
  • Step Into F11
  • Step Out ⇧F11
  • Restart ⇧⌘F5
  • Stop ⇧F5

Continue, restart and stop are straightforward and will do what you expect: continue to the next breakpoint, restart the process and stop the process (and the debugger).

Steps are related to function calls on the current line: you can step over a function call, step into it (look inside and debug) or leave it (step out). Step-over also allows you to run the code line by line, even if the line is not a function call.

Step commands only control what you "see" in the debugger. So "stepping out" or "over" a function will still execute all the code as usual. The debugger will just not bore you with the details, and you'll get jor job done quicker.

Continue

Continue will run the code up to the next breakpoint, or the end of the program. One way of debugging is to add multiple breakpoints on relevant lines beforehand and jump between them using continue:

Using continue to jump to the next breakpoint

So, Continue is handy if you already know which functions or lines are relevant to you. The debugger will pause at pre-defined locations allowing you to inspect the variables and call stack.

Step Over

You can think of step over as going line-by-line in a function but not following function calls (not stepping in). Use it if you're not interested in the details of the function call on the current line, but only want to see how local variables change over time, for example:

Using step over

Step over is a great way to walk trough devlarative code.

Step Into

You can use step-into when you arrive on a line that calls an interesting function, and you want to dig deeper. Once you step into a block, you keep debugging as usual (use continue, step commands, etc.).

Observe how we step over getNameFromReq but step into getGreeting:

Using step into

Step Out

Stepping out is the opposite of stepping in: you can leave a function once you're no longer interested in it. Clicking "Step out" runs the remaining code of the function without you having to keep clicking.

Check out the difference between debugging the two functions - we follow the first one through but step out of the second early:

Using step out

Now you should have a better understanding of the debugger toolbar, how to focus on what matters and skip the irrelevant bits. The navigation commands not only save you time but make the whole debugging activity more enjoyable! Why not try these in your project as an exercise?

Happy debugging! 🥼