Implementing Delegates

an article added by: Sonja Lande at 05312007


In: Categories » » AJAX » Implementing Delegates

Problem

You want to use a delegate architecture to streamline how your code runs and avoid code clashes. Theory When writing JavaScript, very often code will fight for attention. One example of code fighting for attention is the window.onload event. The window.onload event is called once the HTML page has completely loaded and initialized. When the browser calls window.onload, the browser is giving a script the chance to initialize itself with a complete HTML page. For scripters, this method is very interesting, and if there are two toolkits using window.onload, more likely than not one will overwrite the other. Imagine the following code written by one toolkit: window.onload = function() { // initialize toolkit 1} In this code example the toolkit is saying that when the onload event is called, use my functionality. The second toolkit interested in the onload event would assign window.onload to the following: window.onload = function() { // initialize toolkit 2 } The second assignment would work, but it begs the question, what happens to the initialization of toolkit 1? The answer is that it is not called. Toolkits 1 and 2 are fighting for the attention of the onload event, and the winner is whichever toolkit assigns the onload event last. There are three potential solutions to this dilemma:

• Convert the toolkits to use browser-specific tags that will allow them to reference multiple onload functions. The downside of this solution is that you need to write browser-specific code, which increases the maintenance cost of the code.

• Use a function that calls both initializations. The downside is that you need to provide a function that manages both initializations.

• Convert the toolkits to play nicely with each other and not overwrite the other initialization. The downside is that the toolkits have to figure out how to call the other initialization routines. Solution As mentioned, the downside of the first solution presented in the previous section is that it’s browser specific. For Mozilla, the solution is rather elegant because it implements a delegate architecture. For other browsers, the first solution is not as elegant, and thus the final solution is a mixture of the second and third solutions. For the moment, though, let’s focus on the second solution, which is implemented as follows:

   window.onload = function() {
   initializeToolkit1();
   initializeToolkit2();
   }

The windows.onload function is assigned a function that calls the initialization routines of toolkits 1 and 2. The solution works, but it has maintenance issues, since a developer has to add or remove initialization routines. This isn’t a major problem, however. If you look at the implementation of the function, it is the conversion of one function call into two function calls. This is the basis of a delegate.

The initializeToolkit1 and initializeToolkit2 functions have nothing to do with each other, and when called, each could be easily fooled into thinking that it is the only function assigned to the onload event. A delegate is not like a proxy, in that a delegate calls all functions, whereas a proxy will call a function first and then expect the called function to call the other functions. From an implementation perspective, a delegate has a very similar implementation to a proxy. The JavaScript implementation of a delegate does differ from a traditional delegate because there is no single object instance managing all references. In a classical delegate implementation, calling the window.onload function will call a delegate object structure, which calls the managed function references. In the case of the example, that means calling the delegate object structure calls initializeToolkit1 and initializeToolkit2. In the JavaScript delegate implementation, window.onload references a parent delegate function that contains two function references: func1 and func2. The parent delegate function calls both func1 and func2. When parent delegate functions are chained together, func1 (chosen for illustration purposes) references a function to call (initializeToolkit1), and func2 (again chosen for illustration purposes) references the next parent delegation in the chain. In the next parent delegation, one function references the function to call (initializeFunction2), and the other function references another parent delegate function. To understand the serialization problem, imagine trying to serialize window.onload using references:

   window.onload = function() {
   delegates.invoke( this, arguments);
   }
 var buffer = ops.serialize( window.onload);

In the example, window.onload references a function that calls the delegates.invoke global variable method, which will call the functions initializeToolkit1 and initializeToolkit2. If we want to save the state of the HTML page, we will serialize window.onload because it is a standard reference point. Yet serializing window.onload does not serialize delegates. It serializes the reference to delegates, and thus when the page is re-created, the delegates instance will be missing. You may read the previous paragraph and think I’ve lost my marbles, because that is not how serialization is done. You might implement the following solution instead:

   window.unload = function() {
   var buffer = ops.serialize( delegates);
   }`

In this solution, the unload function will be called, and a stream of data that represents the delegates will be generated. But is this solution actually correct? I argue that the solution is delegating the problem of the delegates variable to another location, and it is not solving anything. Imagine, for instance, that you are serializing the state of a page. As you iterate the elements, you are generating the associated functions. So you will serialize window.load and window.unload. The big advantage of this approach is that when coding using a prototype-based language which JavaScript is you are not worried about multiple implementations sharing the same references. Using a value-based approach, you can copy a function from one object to another and not worry about the mixin problem described in article 2-15. Now that you’re familiar with the theory behind delegate implementation, let’s look at the technical details.

   Source: /website/ROOT/scripts/jaxson/common.js
   delegate : function(instance, funcIdentifier,  newFunc) {
   var delegatePrototype = function() {
   var func1 = __replace1;
   var func2 = __replace2;
   func1.apply(this, arguments);
   func2.apply(this, arguments);
   }
   var origFunc;
   if (!instance[funcIdentifier]) {
   origFunc = function() { };
   }
   else {
   origFunc = instance[funcIdentifier];
   }
   instance[funcIdentifier] =  Generics.expand(delegatePrototype,
   {
   __replace1 : origFunc,
   __replace2 : newFunc
   });
   },
   Source: /website/ROOT/ajax articles/javascript/exceptions.html
   window.onload = function() {
   window.onerror = function(msg, file, location)  {
   info("window.onerror1", "Msg  (" + msg + ") file (" + file + ") location (" +
   location + ")");
   }
   }
   ops.delegate(window, "onload",  function() {
   window.onerror = function(msg, file, location)  {
   info("window.onerror2", "Msg  (" + msg + ") file (" + file + ") location
   (" + location + ")");
 }});

In the example, the window.onload function is assigned a function. The next line of source code uses the ops.delegate method call to convert the assigned function into a delegate. Thus, when the window.onload event is called, the two functions are called, both of which assign window.onerror. A consequence of using delegates is that a programmer might use delegates, but forget the resources they assign using delegates are shared as well. Therefore, a good programmer won’t assign window.onerror, but will use a delegate to assign window.onerror. When writing code where a method or function callback needs to be shared, you can use delegates, but keep the following points in mind:

• Delegates allow programmers to share a method callback, but they should not assume that the resources in their method implementation are exclusive.

• Delegates solve the problem where a single method call can be used to make multiple method calls.

• Delegates cannot return values because multiple methods may return values; thus, delegates should always use code blocks. Code blocks are inherently single, multiple, or no result oriented. Using code blocks does not require the infrastructure to do anything special when data has to be returned.

• Delegates can be implemented using reference or value duck typing, with the main difference between them being the ability to serialize.

legal notice

Our website is not responsible for the information contained by this article. Web-articles is a free articles resource.
Suggestion: If you need fresh, daily updated content for your website, feel free to use our service. Click here for more information.

Useful tools and features

Link to this article from your page    Send this article to you or to a friend
If you like this article (tutorial), please link to it from your web page using the information above.

related articles

1. Ajax
Given the recent interest in Ajax, you’d be forgiven for thinking it was a new technology. In fact, the XMLHttpRequest object has been around for years. In technical terms, asynchronous JavaScript interaction with the server is nothing new. All of the other elements of the Ajax model have also been around for quite some time: CSS, (X)HTML, and DOM Scripting. Yet in 2005, interest in this methodology soared. Could it really be that simply giving this approach a snappy name like Ajax was responsible for the sudde...

2. Understanding the Definition and Philosophy of Ajax
The focus of this article is to provide solutions to some common, general problems and questions that are bound to arise before or during development of Asynchronous JavaScript and XML (Ajax) and Representational State Transfer (REST) applications. These common questions are not always technical in nature, often leaning more toward theory or philosophy of development. The problem with these kinds of questions is that once you begin to think about them, you keep going in a circle and end up where you star...

3. Understanding the Definition and Philosophy of Web Services and SOA
Understanding the Definition and Philosophy of Web Services and SOA Wikipedia offers the following definition of Web services:4 The W3C defines aWeb service as a software system designed to support interoperable machine-to-machine interaction over a network. This definition encompasses many different systems, but in common usage the term refers to those services that use SOAPformatted XML envelopes and have their interfaces described by WSDL. For ex...

4. Understanding the Definition and Philosophy of REST
Understanding the Definition and Philosophy of REST REST is a controversial topic among Web service enthusiasts, because it’s considered to stand for the opposite of what Web services and SOA are trying to achieve. The problem with this thinking is that REST is not in contradiction with the abstract definition of SOA and Web services. REST is in contradiction with technologies such as SOAP, WSDL, and WS-* specifications. The following offers a quick definition of REST:...

5. The Easiest Way to Get Started with Ajax and REST
The Easiest Way to Get Started with Ajax and REST Problem You want to know the best way to get started with writing Ajax and REST. Solution When developing an Ajax and REST application, you must decide on the tools and frameworks you’ll use. The choice is simple: Use whatever you’re using today, and write some Ajax applications. You don’t need to change the tools you’re using today. Whether you’re using ASP.NET, JavaServer Pages (JSP), PHP, Ruby, or Python, you...

6. Testing a Dynamic Contract with Ajax
Coding the Contract Using Test-Driven Development Techniques Coding the contract using agile and test-driven development techniques requires writing a number of tests and implementing aMock URL layer. Problem You want to code the contract using these development techniques. Solution To demonstrate, let’s define a use case, implement the use case as a contract, write a test case(s) to implement the contract, implement the contract in the Mock URL, and finally...

7. Testing the Client Side Logic
Problem You want to effectively test your application’s client-side logic. Theory Testing GUI code tends not to be a productive task because of the complications that arise. The main complication is how to test the correctness of a user interface. Imagine a situation where clicking a button causes a table to be filled with data. Now imagine that when a check box is checked and the button is clicked again, a different table is filled with content. The fact that clicking the same button results in two ...

8. Understanding JavaScript and Types
Understanding JavaScript and Types Problem You want to work around the fact that JavaScript does not have types declared for its variables. Theory JavaScript code does not have any variables with a declared type. The lack of typed variables is apparent when you declare functions. That said, not having typed variable declarations does not mean JavaScript has no types or no type safety. Let’s start out with the simple declaration of a function, as illustrated by the following ex...