Online Book Reader

Home Category

AJAX In Action [97]

By Root 4154 0
the instanceof operator would have counterintuitive behavior, as outlined in table 5.1.

Licensed to jonathan zheng

186

CHAPTER 5

The role of the server

Table 5.1 Behavior of instanceof operator across frames

Object Created In

instanceof Invoked In

Obj instanceof Object Evaluates To

Top-level document

Top-level document

true

Top-level document

IFrame

false

IFrame

Top-level document

false

IFrame

IFrame

true

Importing the same object definition into multiple scripting contexts is not as simple as it first looks. We can avoid it by providing a factory method as part of our top-level document’s API, for example:

function createPlanetInfo(name,description){

return new PlanetInfo(name,description);

}

which our script can then call without needing to refer to its own version of the PlanetInfo type, thus:

The showPopup() function in listing 5.4 is essentially a factory for the ScriptIframePopup object. This approach works and does what we want it to. We need to send a small amount of HTML boilerplate with each page, but much less than with the contentcentric solution. The biggest drawback of this approach appears to be the creation of a separate JavaScript context. There is a way to avoid that altogether, which we will look at now.

Loading scripts using XMLHttpRequest and eval()

JavaScript, like many scripting languages, has an eval() function, which allows any arbitrary text to be passed directly to the JavaScript interpreter. Using eval() is often discouraged, or noted as being slow, and this is indeed the case when it is called regularly on lots of small scripts. However, it has its uses, and we can exploit it here to evaluate scripts loaded from the server using the XMLHttpRequest object. eval() performs with reasonable efficiency when working on fewer, larger scripts.

Licensed to jonathan zheng

The details: exchanging data

187

Our planetary info example is rewritten to use eval() in the following code: function showInfo(event){

var planet=this.id;

var scriptUrl="script_"+planet+".js";

new net.ContentLoader(scriptUrl,evalScript);

}

function evalScript(){

var script=this.req.responseText;

eval(script);

}

The showInfo() method now uses the XMLHttpRequest object (wrapped in our ContentLoader class) to fetch the script from the server, without needing to wrap it in an HTML page. The second function, evalScript(), is passed to the ContentLoader as a callback, at which point we can read the responseText property from the XMLHttpRequest object. The entire script is evaluated in the current page context, rather than in a separate context within an IFrame.

We can add the term script-centric to our pattern language now and make a note that there are two implementations of it, using IFrames and eval(). Let’s step back then, and see how script-based approaches compare with the contentbased style. Problems and limitations

When we load a script directly from the server, we are generally transmitting a simpler message, reducing bandwidth to some extent. We also decouple the logic from the presentation to a great degree, with the immediate practical consequence that visual changes aren’t confined to a fixed rectangular portion of the screen as they are with the content-centric approach.

On the downside, however, we introduce a tight coupling between client and server code. The JavaScript emitted by the server is unlikely to be reusable in other contexts and will need to be specifically written for the Ajax client. Further, once published, the API provided by the client will be relatively difficult to change.

It’s a step in the right direction, though. The Ajax application is starting to behave more like an application and less like a document. In the next style of client-server communication that we cover, we can release the tight coupling between client and server that was introduced here.

Licensed to jonathan zheng

188

CHAPTER 5

The role

Return Main Page Previous Page Next Page

®Online Book Reader