Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Ajax In Action (2006).pdf
Скачиваний:
63
Добавлен:
17.08.2013
Размер:
8.36 Mб
Скачать

Debuggers 577

A number of debuggers for JavaScript are available. Free debugging tools include the Venkman plug-in for Mozilla Firefox and the Microsoft Script Debugger (see the Resources section at the end of this appendix for information on both of these) for Internet Explorer. Venkman supports all of the advanced features described previously, as well as having an inbuilt profiling tool, which we describe in chapter 7. The Microsoft Script Debugger supports call stack navigation and an “immediate window” for executing JavaScript on the fly, including querying and reassigning local variable values.

Visual Studio and Komodo IDEs also support JavaScript debuggers with an advanced set of capabilities.

Server-side debugging

In addition to being able to debug JavaScript on the client, it is often useful to debug the server-side code, too. Java and .NET IDEs generally ship with highquality debuggers. Eclipse’s Java tools and Visual Studio both offer debugging out of the box, as do most other IDEs. For debugging Java-based web applications, the JBoss application server and Eclipse plug-ins provide a simple system for deploying and debugging web applications. Web development versions of Visual Studio ship with a built-in ASP.NET-enabled web server for development purposes. Visual Studio is the only development environment to my knowledge to support debugging of client-side and server-side code within the same user interface.

It can be also very useful to debug network traffic. Again, a range of free and commercial tools is available for this purpose. Let’s look at them now.

A.3.3 HTTP debuggers

Between the Ajax client and the web server, all communications take place over HTTP. This in itself can be a complex business and may be a source of errors. At times, it is reassuring to be able to inspect the HTTP traffic, to look at the headers, querystrings, content of the request and response, and sequence of interchanges.

LiveHTTPHeader

Mozilla Firefox supports an extension called LiveHTTPHeaders, which is capable of logging HTTP traffic from the browser (figure A.9). Request and response headers are recorded and displayed, and they can be exported as text files to provide a permanent record of an Ajax session. Querystrings from GET and POST methods are also recorded, but the response content is not.

578APPENDIX A

The Ajax craftsperson’s toolkit

Figure A.9 The Mozilla LiveHTTPHeaders extension can log HTTP traffic and present details of request and response headers.

LiveHTTPHeaders supports only reading headers. Other Firefox extensions are available for modifying headers in transit, such as the Modify Headers extension.

Fiddler

Microsoft Research recently released a .NET-based application called Fiddler that fulfills a similar role to LiveHTTPHeaders but also allows for scripted rewriting of headers on the fly, using JavaScript. This provides a similar capability to the ability to change variable values in some debuggers during a session, and it can be used to quickly work around bugs in an application while it is running.

Unlike LiveHTTPHeaders, which is integrated into the browser, Fiddler is an independent process that acts as a proxy between the client and server. As such, it can be used with any combination of browser and web server.

Charles

Charles is a shareware tool written in Java. Like Fiddler, it acts as a proxy between browser and server. It can log request and response data, including the content, and export sessions as spreadsheet files. It also provides a highly configurable built-in bandwidth-shaping tool, which allows easy simulation of very slow connections over a fast LAN or even when the client and server are both deployed to the same machine.

There are a number of other useful tools in this category, which we don’t have space to cover fully here. If Charles and Fiddler don’t do what you want, a quick online search for “Ethereal” or “Apache TCPMon” might help you out.

This concludes our review of off-the-shelf debugging tools. By combining a server-side code debugger, a JavaScript debugger on the client, and an HTTP

Debuggers 579

debugger in between, it is possible to intercept your application at any point in its lifecycle and be able to see what it is really getting up to.

Debuggers are, by their nature, intrusive. Although they are very powerful in many ways, there are times when a background logging system is preferable. Plenty of mature server-side logging frameworks are available, such as Apache log4j for Java, but, once again, the JavaScript toolset is lagging. In the final part of this section, we’ll look at a simple logging tool written in JavaScript that can be integrated into your browser code to provide a record of background activity.

A.3.4 Building your own cross-browser output console

A debugger gives a developer a very detailed view of running code, but it interrupts the ordinary flow of events. When tracking a user’s interactions for usability testing or monitoring the execution of code in a tight loop, it is sometimes more useful to log activity without interrupting the flow.

Web browser JavaScript doesn’t provide a built-in logging facility. (The Mozilla JavaScript console may look like one at first glance, but it can only be written to by the browser and by extensions.) In this section, we’ll develop our own simple logging system and demonstrate its use in one of our example applications. Let’s sketch out our requirements first. We can’t write to a local file because of the JavaScript security model, so we’ll opt to write to an on-screen console element instead. We want to be able to append messages to our console. Ideally, we’d like to be able to use HTML markup in our logging, as well as plain text. We’d also like to clear the console of existing messages.

To keep things simple, we’ll pass a DOM element in as an argument to the object constructor. The placement of the console can then be determined on a page-by-page basis. The constructor simply sets up a two-way reference between the DOM element and the console object itself:

Console=function(el){

this.el=document.getElementById(el);

this.el.className='console';

this.el.consoleModel=this;

this.clear();

}

To append to the console, we simply pass in an argument, which may be a textual string or a DOM element, and optionally pass in a CSS class name as well:

Console.prototype.append=function(obj,style){ var domEl=styling.toDOMElement(obj);

if (style) { domEl.className=style;

580APPENDIX A

The Ajax craftsperson’s toolkit

}

this.el.appendChild(domEl);

}

The toDOMElement() method calls a generic styling function, which ensures that the message is wrapped up as a DOM element. If the argument is already a DOM element, it is returned unchanged. If it is a string, it is wrapped in a DIV element:

styling.toDOMElement=function(obj){ var result=null;

if (obj instanceof Element){ result=obj;

}else{

var txtNode=document.createTextNode(String(obj)); var wrapper=document.createElement('div'); wrapper.appendChild(txtNode);

result=wrapper;

}

return result;

}

To clear the console, we simply remove all child elements from it, one by one:

Console.prototype.clear=function(){

while(this.el.firstChild){

this.el.removeChild(this.el.firstChild);

}

}

That provides a simple implementation of an in-browser logging console. Let’s have a look at how we use it now. We’ll take the ObjectViewer example from chapters 4 and 5. First, we define a DOM element in our page to contain the logging console

<div id='console'></div>

and a CSS class to position it on screen for us:

div.console { position:absolute; top:32px; left:600px; width:300px; height:500px; overflow:auto;

border: 1px solid black; background-color: #eef0ff;

}

Debuggers 581

We are using absolute positioning here, but we could use any Ajax user interface technique to do the job for us. Next, we need to create the logging object. We’ll define it as a global variable in this example for convenience.

var logger=null; window.onload=function(){

logger=new Console("console"); logger.append("starting planets app");

...

}

We initialize the logger in the window.onload event, so that the DOM element that it requires is guaranteed to be created. Now let’s suppose that we want to log a message whenever a planet object is created in our domain model. We simply need to invoke logger.append():

planets.Planet=function

(id,system,name,distance,diameter,image){

this.id=id;

...

logger.append("created planet object '"+this.name+"'");

}

Similarly, we can add logging statements to the ObjectViewer code when we edit values and launch pop-up subwindows, to the ContentLoader object when we load network resources, and so on, in order to track the behavior of our codebase while it is running. We can style important messages, for example, network failures:

net.ContentLoader.prototype.defaultError=function(){ logger.append("network error! "+this.url, "urgent");

}

Figure A.10 illustrates the logger console in operation as part of the modified planet viewer application.

This demonstration shows how straightforward it is to add simple logging capabilities to an Ajax application. The system is considerably simpler than server-side logging frameworks such as Apache’s log4j. We leave it as an exercise for the reader to add multiple categories of logging that can be turned on and off independently.

Now let’s move on to our next type of tool: the DOM inspector.