LA.NET [EN]

Mar 04

During the next days, I”ll be writing about the AJAX Toolkit. I”ll start with the client part and then I”ll proceed to the server part. The main objective is to document some of my findings and put them all in a place where i can search them. Today I”m going to write about deferred operations. A deferred operation can be seen as an operation that is scheduled to run sometime in the future. Yes, you can already do this with javascript programming by using the window.setTimeout method. The advantage of using the Toolkit is that you”ll get a class that let”s you start or cancel a deferred operation. Without further ado, let”s see an example. The following page let”s you introduce a name and then call  a method (which you can right away – by using the sync button- or on a deferred way, by using the async button):

<%@ Page Language=”C#” AutoEventWireup=”true” CodeFile=”Default.aspx.cs” Inherits=”_Default” %>
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.1//EN” “http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd”>
<html xmlns=”http://www.w3.org/1999/xhtml”>
 <head runat=”server”>
 <title>Untitled Page</title>
 <script type=”text/javascript”>
     var _deferred = null;
     function deferred(name){
           alert( “you”ve sent me ” + name );
    }
    function handleLoad(){
         _deferred = new AjaxControlToolkit.DeferredOperation( 2000, null, deferred );
   }
   function sync(){
          _deferred.set_delay( -1 );
         _deferred.post( $get(“name”).value );
   }
   function async(){
         _deferred.set_delay( 2000 ); //just to garantee that the delay is not overriden by sync method being called previously
        _deferred.post( $get(“name”).value );
   }
   function cancel(){
        if( !_deferred.get_isComplete() ){
           _deferred.cancel();
        }
   }
</script>
</head>
  <body onload=”handleLoad()”>
     <form id=”form1″ runat=”server”>
         <asp:ScriptManager ID=”ScriptManager1″ runat=”server”>
             <Scripts>
                <asp:ScriptReference Path=”Threading.js” />
            </Scripts>
        </asp:ScriptManager>
       <div>
        <span>Name:</span>
        <input type=”text” id=”name” />
        <input type=”button” id=”start” value=”sync” onclick=”sync()” />
        <input type=”button” id=”Button1″ value=”async” onclick=”async()” />
        <input type=”button” id=”Button2″ value=”cancel” onclick=”cancel()” />
      </div>
  </form>
</body>
</html>

There are some points worth noticing here:

  • The DeferredOperation constructor receives three parameters: the delay (in ms), the context (over which the a method will be called) and a reference to the callback method;
  • The DeferredOperation class has other important properties. For instance you can decide if an exception that happens during the method execution is thrown (_throwExceptions), you can get the return value of the method (_asyncResult), etc;
  • You can execute the method synchronously (by calling the post method – sort of; more info below) or asynchronously (ie, defer it x milliseconds), by calling the beginPost method.

As you can see from the previous example,I”m calling a “global” method (again,sort of :)) so i”m passing null for my context. One curious thing you”ve seen in the previous code is that for getting a synch method call you can”t only call the post method. you need to garantee that when you call that method, you”ve set the delay property to -1 (yes, if you”ve set it to a different number, you”ll get a deferred method call). Well, I”m not sure about you, but I really don”t like this approach. If you have a XXX method and another beginXXX method, it”s natural to assume that the XXX method is synchronous and that the beginXXX will do the same thing asynchronously. Having to set the delay to -1 is not intuitive.  So, i really expected that calling post would call the deferred method imediately, instead of just starting the timer for the deferred method call…

Another thing you should now is that you can pass a callback method and an error callback method when you use the beginPost method. Those methods will be called after the execution of the deferred method finishes or if the deferred method generates an exception.

Finally, you should note that a deferred method execution can be cancelled by calling the cancel method.

Update: I”ve updated the code and I”ve declared _deferred as a page variable. I deleted it by mistake while arranging the contents in live writer. Thanks Bertrand for pointing this out.

2 comments so far

  1. Bertrand Le Roy
    5:55 am - 3-5-2007

    You should declare _deferred, or you”ll get a warning in Firefox strict mode.

  2. Luis Abreu
    8:30 am - 3-5-2007

    howdy.

    you”re right. I did declare it, but it got deleted when i was tabbing the content. thanks.