• No results found

7-7 Using the V8 Debugger Problem

In document Node js Recipes Cory Gackenheimer pdf (Page 182-187)

You need to step through and debug your Node.js application.

Solution

Node.js runs on Google’s V8, which has a built-in debugging mechanism. Because of this, Node.js allows you to debug the source utilizing this tool. You will create a solution that will help you gain an understanding of just how the debugger works and of what insights it can give you to your code. Listing 7-15 shows a simple HTTP server that will require a second module (shown in Listing 7-16).

Listing 7-15. HTTP Server /** * Debugging */ var http = require('http'), mod = require('./7-7-2');

server = http.createServer(function(req, res) { if (req.url === '/') {

debugger;

mod.doSomething(function(err, data) {

if (err) res.end('an error occured'); res.end(JSON.stringify(data)); }); } else { res.end('404'); } }); server.listen(8080);

Chapter 7 ■ DisCovering other noDe.js MoDules

Listing 7-16. Required Module /**

* Debugging */

exports.doSomething = function(callback) { debugger;

callback(null, { status: 'okay', data: ['a', 'b', 'c']}); };

There are a few things that might be slightly different from your typical Node.js application; in particular you can see some ‘debugger;’ statements. These will be directives to tell the V8 debug mechanism to pause execution of your program. This process begins by starting your Node.js application with the ‘debug’ flag.

How It Works

Google designed the V8 JavaScript engine, which powers Node.js, to allow for debugging of the JavaScript that is executing within the engine. Node.js supports V8 debugging in two ways. One way is to implement the V8 debugger protocol in a manner that will create the debugger, listening on a TCP port. This is useful if you are creating or using a third-party debugging tool that is coordinated to utilize the protocol. To do this, start your Node.js application, 7-7-1.js, with the command $ node --debug 7-7-1.js. This will begin the debugger and listen on localhost:5858 for hooks into the debugger. This allows for debugging clients to be created that communicate with the debugger. Fortunately, Node.js comes with its own V8 debugger client. You can access an application that you started in debug mode with the - -debug flag by typing $ node debug into the console.

The Node.js built-in debugger can be accessed by starting your Node.js application with the ‘debug’ parameter. Listing 7-17. Starting the Node.js debug CLI

$ node debug 7-7-1.js

This will start your application but with the debugger attached. The output in your console will show you that the debugger has started listening, and it will show the first line of JavaScript code, which the debugger will break by default.

Listing 7-18. Initial State of the Debugger < debugger listening on port 5858 connecting... ok break in 7-7-1.js:5 3 */ 4 5 var http = require('http'), 6 mod = require('./7-7-2'); 7 debug>

You now have a ‘debug>’ prompt. This is the command-line interface to the debugger. You can walk through the basics of debugging by following the next steps. First, you can add a watch to an object or property in your application. To do this you type ‘watch’ followed by any expression you wish to watch.

Chapter 7 ■ DisCovering other noDe.js MoDules

So, in your solution you can watch for the request URL by using the watch command and passing ‘req.url’ as the expression.

debug> watch('req.url')

You are also able to list all the watchers that are currently active in your debugger session. The results will print the active watchers and their values to the console. The current values are given the immediate context of where the JavaScript code is paused.

debug> watchers

0: req.url = "<error>"

Recall that in your application code, you created two places where you called ‘debugger;’. It will pause the execution at these points in your application. However, there may be times when you do not wish to add debugger statements and you would just like to set a breakpoint in your code. To do this, the debugger has several breakpoint methods available. To set a breakpoint on the current line, simply type setBreakpoint() into the debug console. Alternatively, you can use the shorthand sb() to set a breakpoint. The setBreakpoint method also accepts a line number, so you can predetermine a line to break on. You can do this in your code by setting a breakpoint on the server.listen(8080) method. debug> sb(21) 1 /** 2 * Debugging 3 */ 4 5 var http = require('http'), 6 mod = require('./7-7-2'); 7

8 server = http.createServer(function(req, res) { 9 if (req.url === '/') {

10 debugger;

You can also break on another file that will be loaded into your application. To do this, pass the file name and the line number to the setBreakpoint method.

debug> sb('7-7-2.js', 5)

Warning: script '7-7-2.js' was not loaded yet. 1 /** 2 * Debugging 3 */ 4 5 var http = require('http'), 6 mod = require('./7-7-2'); 7

8 server = http.createServer(function(req, res) { 9 if (req.url === '/') {

10 debugger;

Here you see that you have set the breakpoint on the initial line of code in the file 7-7-2.js. Once you continue the execution of the program, the breakpoint will pause the execution of the program again as soon as that line of code is hit.

Chapter 7 ■ DisCovering other noDe.js MoDules

At this point, you are ready to navigate through your application using the debugger. The debugger, like most debuggers, exposes methods that allow you to step through and continue the execution of your code. The most granular method is the step in command. This is called by typing ‘step', or 's', for shorthand. From the beginning of the execution of your debugging instance, if you step, it will move you to the next area of execution. In this instance it has moved into the module.js file and is beginning the process of adding the modules you required in the source. debug> s break in module.js:380 Watchers: 0: req.url = "<error>" 378 379 function require(path) { 380 return self.require(path); 381 }

382

From here you will want to continue. Continuing execution will run until the next breakpoint is hit. If there are no other breakpoints, the application will run normally until you manually pause it with the pause command. A continuation can be triggered by ‘cont', or ‘c'. In your example, this will move you through the module import code and to the breakpoint, which you set on the ‘7-7-2.js’ file, line 5.

debug> c break in 7-7-2.js:5 Watchers: 0: req.url = "<error>" 3 */ 4 5 exports.doSomething = function(callback) { 6 debugger;

7 callback(null, { status: 'okay', data: ['a', 'b', 'c']}); debug> c break in 7-7-1.js:21 Watchers: 0: req.url = "<error>" 19 }); 20 *21 server.listen(8080); 22 23

Continuing one more time, you will hit the breakpoint you set on line 21 of ‘7-7-1.js’; this is the last breakpoint you set. However, there are debugger statements that you will hit once a connection is made to your HTTP server. After continuing through this, you can then make a request to your webserver, 'http://localhost:8080/’. Because of the debugger; statement, this will pause the execution at precisely the location in your connection listener callback. debug> c

break in 7-7-1.js:10 Watchers:

Chapter 7 ■ DisCovering other noDe.js MoDules

8 server = http.createServer(function(req, res) { 9 if (req.url === '/') {

10 debugger;

11 mod.doSomething(function(err, data) {

12 if (err) res.end('an error occured');

From here, you can step into the next execution. This is done using the ‘next’, or ‘n’, command in the debugger. Performing ‘next’ twice, you end up at the debugger; statement within your ‘7-7-2.js’ module.

debug> n break in 7-7-1.js:11 Watchers: 0: req.url = "/" 9 if (req.url === '/') { 10 debugger;

11 mod.doSomething(function(err, data) {

12 if (err) res.end('an error occured'); 13 debug> n break in 7-7-2.js:6 Watchers: 0: req.url = "<error>" 4 5 exports.doSomething = function(callback) { 6 debugger;

7 callback(null, { status: 'okay', data: ['a', 'b', 'c']}); 8 };

You can now step out of this method by using the ‘out’, or (‘o’), command. debug> o break in 7-7-1.js:19 Watchers: 0: req.url = "/" 17 res.end('404'); 18 } 19 }); 20 21 server.listen(8080);

Other than step, next, continue, and out, there is the ‘pause’ command. This will pause the execution of any code that is running at the time.

While you are stepping through your code, it is sometimes necessary to get some more information about what is happening in your application. The debugger has utilities for this as well. First, when you are paused at a breakpoint, if you want to see more of the surrounding code, you can do this by using the ‘list(n)’ command. This will show the code surrounded by ‘n’ lines before and after the currently paused location, which can be very useful in gathering more context to what is currently taking place in the debugger. Another useful feature is the ‘backtrace’ (‘bt’) command. This will show the trace of execution path for the current point in the program.

Chapter 7 ■ DisCovering other noDe.js MoDules

Listing 7-19. Example of backtrace from Within the doSomething Method of the 7-7-2.js Module debug> bt

#0 exports.doSomething 7-7-2.js:6:2 #1 7-7-1.js:11:7

You can also view the loaded files by using the ‘scripts’ command. Importantly, if you need to dig deeper into the code, you can use the debugger’s read–eval–print loop (REPL) module by using the ‘repl’ command.

Debugging a Node.js application is treated as a high priority with the built-in command-line interface for debugging your application using the V8 debugger. You will find these tools to be useful when you track down anomalies and bugs in your code.

7-8. Parsing URLs

In document Node js Recipes Cory Gackenheimer pdf (Page 182-187)