After setting up the environment for Deno development , the next step is to learn how to debug your scripts using the built-in debugger. Even if you are proficient in Typescript from your Node.js experience, write a clean code and consistently adhere to industry best practices, there may still be occasions when you need to debug your Typescript files. This is especially true when learning a new Javascript runtime that introduces new APIs. Debugging not only helps troubleshoot your scripts and pinpoint code errors but also aids in learning and understanding the strengths and weaknesses of new technology.
First off, we’re going to create a script, which we’ll use as a learning tool for mastering Deno’s built-in debugger. The script will fetch data from the todo REST API of jsonplaceholder.typicode.com, which provides free and reliable APIs for testing and prototyping.
// tasks.ts
class Tasks {
async format(id : number) : Promise<string> {
const ss : string = await fetch(`${this.endpoint}/${id}`).then( res =>{
return res.json().then( task => {
return `Task #${task.id} => ${task.title}`;
})
}).catch( err => {
console.log('Error: ', err.message);
return '';
});
return ss;
}
private readonly endpoint: string = 'https://jsonplaceholder.typicode.com/todos';
}
const tasks = new Tasks();
console.log ( await tasks.format(1) );
console.log ( await tasks.format(2) );
In this script, we fetch and display two tasks using the fetch API. Let’s see if it works as expected by running the script. Please remember to add the --allow-net option because the script needs to make an HTTP request.
$ deno run --allow-net tasks.ts
Task #1 => delectus aut autem
Task #2 => quis ut nam facilis et officia qui
Invoking the Deno Debugger
Let’s say we aim to improve the format method to display more details about the task. However, we’re unsure about the fields in the task object returned from the API. To solve this, we’ll debug the script and set a breakpoint at line 6. This will allow us to inspect the content of the task variable and make appropriate changes.
To start the debugger, and make it stop in the first line of the script we use --inspect-brk option.
$ deno run --allow-net --inspect-brk tasks.ts
Debugger listening on ws://127.0.0.1:9229/ws/014b4eb9-59c4-4e91-a0ec-4a67259c325a
Visit chrome://inspect to connect to the debugger.
Deno is waiting for debugger to connect.
The debugger is now set to listen at the provided address and is waiting for a connection from the debuggers. As recommended, we will use the Chrome debugger to debug the script. Open Chrome and go to chrome://inspect. You should see something like this:
Now, find your script by its path among all the displayed items and click the corresponding ‘Inspect’ link. This action will open a new Chrome Debugger web tools window, where our script is displayed and paused at the first executable line. In the command line that started the script, you should see the message “Debugger session started.”
$ deno run --allow-net --inspect-brk tasks.ts
...
Deno is waiting for debugger to connect.
Debugger session started.
Rest assured, the debugger displays your TypeScript file, not its JavaScript version. If you’ve tried debugging TypeScript with Node.js, you know it requires additional steps. On the other hand, debugging with Deno is much simpler and superior to Node.js. Deno offers a seamless and effortless process for debugging TypeScript.
Adding a breakpoint via Debugger UI
Now, we can utilize the familiar features of the Chrome debugger. We can resume script execution (F8), step over the next function call (F10), step into the next function call (F11), step out from the current function (SHIFT+F11), and step one sentence (F9). We can also add breakpoints, watch the value of variables and expressions, observe variables’ values in local and global scopes, and check the call stack.
Let’s add a breakpoint at line 6 and watch the task variable. When we resume the script execution, the debugger will pause, allowing us to see what the endpoint returned.
Adding a Breakpoint via debugger statement
Instead of pausing the script right off the first line with --inspect-brk option, and then adding the break using the Chrome UI, We can add the ‘debugger’ statement exactly where we want to suspend the script, and then invoke the deno run with --inspect-wait option. This cool trick makes Deno start listening for the debugger and wait for the connection before running the script. So when the debugger connects (like when we hit ‘inspect’ in chrome://inspect), the script gets back on its feet and will pause when it hits the debugger statement. Neat, right?
Deno debugger in Action
we see couple of ways you can go about debugging with the Chrome debugger and Deno runtime – it’s all about what works best for you and your needs.
If you use the --inspect-brk option, Deno will kindly pause the debugger at the first executable line of the script for you. Or, you could use the --inspect-wait option together with a ‘debugger’ statement, and it will pause the debugger at the line you added the ‘debugger’ statement.
Whichever way you go, once the script is paused, you’re free to use the Chrome debugger UI to resume script execution, step over/into/out of function calls, and take a look at variable values. It’s your playground to learn Deno!