Chapter 13

Advanced Asynchronous Programming with jQuery Deferred

WHAT’S IN THIS CHAPTER?

  • The Promises/A Proposal
  • The jQuery Deferred Object

In this chapter, you learn about the jQuery Deferred object. $.Deferred, introduced in version 1.5, is a chainable utility object that provides fine-tuned control over the way callback functions are handled. For example, instead of merely having a single success method for your $.ajax calls, you can now define multiple callbacks that can be combined with precision and flexibility.

This chapter also introduces the CommonJS Promises/A proposal that fed the design of $.Deferred. Following that foundation, you learn about the jQuery implementation in detail.

Leveraging the power of $.Deferred will make some unpleasant coding patterns disappear. Monolithic success blocks, chock full of application logic, will be a thing of the past. Awkward timing with asynchronous requests and unmaintainable function calls buried at the end of other function calls can be put to bed with $.Deferred. $.Deferred pulls all of that logic up a level and gives it a clear structure that’s more maintainable, more flexible, and is, as is often the case with jQuery, a fun pattern to use.

BUILDING BLOCKS

$.Deferred is built on existing work and concepts from sources outside the jQuery project. To understand the feature in the fullest, it’s useful to look at those sources directly. This section will outline the origin of the pattern, which will ease you into an understanding of jQuery’s specific implementation.

Promises

Basically defined, a promise is a proxy for the result of an action that will happen at an unspecified time in the future.

Although they’re relatively new to jQuery, software promises have been around for a good while. The name and concept of promises dates back to a paper written in 1976 by Daniel P. Friedman and David Wise. Though language implementations are generally more academic than practical, library implementations exist for Java, Scala, Ruby, Perl, Python, and Common Lisp. Closer to home, a major JavaScript implementation has been in place in the dojo framework from version 0.9.

Because they’re so easily asynchronous, they’re particularly suited to web programming, so it was inevitable that they’d land in jQuery.

The Promises/A Proposal

jQuery’s specific implementation is based on the Promises/A proposal from CommonJS.

CommonJS is a group centered on interoperability in JavaScript and the growth of a healthy JavaScript ecosystem similar to the ones that have developed around other languages like Python, Ruby, and Java. The group’s main focus is on the question of modules, which the Common JS Modules API addresses directly, but they’ve worked on several other language features. One is promises. The CommonJS wiki lists several proposals for the Promises pattern. Promises/A proposal is from Kris Zyp. It’s defined as follows:

A promise represents the eventual value returned from the single completion of an operation. A promise may be in one of the three states, unfulfilled, fulfilled, and failed. The promise may only move from unfulfilled to fulfilled, or unfulfilled to failed. Once a promise is fulfilled or failed, the promise’s value MUST not be changed The immutable characteristic of promises are important for avoiding side-effects from listeners that can create unanticipated changes in behavior and allows promises to be passed to other functions without affecting the caller, in same way that primitives can be passed to functions without any concern that the caller’s variable will be modified by the callee.

A promise is defined as an object that has a function as the value for the property ‘then’.

http://wiki.commonjs.org/wiki/Promises/A

The following code sample presents a simplified look at the concepts presented in the Promises/A proposal.

Assuming that ajaxPromise returns a promise that can be in one of three states (unfulfilled, fulfilled, or failed), the following illustrates the general principle:

image
var promise = ajaxPromise() {
  //XHR request
  //state is set to fulfilled, unfulfilled, or failed
  //depending on the result of the request
  return state 
};
 
function unfulfilled(){
  //handle negative result
}
function fulfilled() {
  //handle successful result
}
function failed(){
  //Error!
}
 
promise.then( 
  unfulfilled, 
  fulfilled, 
  failed
);

Code snippet is from pseudocode.txt

In English, ajaxPromise goes off, gets some data with an XMLHttpRequest, and when the request finishes, it returns a promise in one of the three states. The then() method routes the result to one of three functions designed to handle that state. None of that logic is bound to ajaxPromise itself. It’s all handled outside the function, which allows ajaxPromise to remain much more generic because less application logic is bound to it directly.

Now that you’ve got some history on the concept, in the next section, you look at the power of jQuery’s Deferred implementation.

THE JQUERY DEFERRED OBJECT

jQuery’s implementation adds onto the basic premise of the promise with several useful enhancements. Importantly, it also integrates directly with one of the core features of the library, $.ajax, so Deferred opens up a world of possibilities once you’ve got your head wrapped around them.

As is the jQuery way, the format of the implementation is heavy on the ability to chain methods in a convenient way. It’s also written in a friendly, human-readable style.

This section looks at jQuery’s basic implementation and walks through some of the more advanced features available.

$.when, Deferred.done, and Deferred.fail

When working with Deferreds, you’ll find that a lot of activity flows through the new jQuery method $.when. $.when accepts either one or more Deferred objects (which importantly include $.ajax calls) or a plain object.

If a Deferred is passed to $.when, its promise object is returned by the method. You see more about how to manage jQuery’s promises in a later section, but additional methods are then available to chain and structure callbacks.

The first two methods are Deferred.done and Deferred.fail.

Deferred.done accepts a single function or array of functions to fire when a promise is resolved successfully.

Deferred.fail also accepts a function or array of functions. It fires when a promise is rejected.

As a note, if an argument is passed to $.when and it is not a Deferred, it is treated as a resolved Deferred. If no other Deferred objects are passed to $.when, then Deferred.done fires.

The following code presents a bare-bones jQuery Deferred example using $.when, Deferred.done, and Deferred.fail.

The example starts off by defining three functions. The function fib does some math and then displays an unordered list with the results of that calculation. Two other functions are then defined, success and failure. These are simple functions that change the messaging in an h1 depending on the result of the first function. The interesting piece is that one or the other will fire depending on whether the promise is resolved or rejected.

image
 <!doctype html>
<html>
<head>
<meta charset=”utf-8”>
</head>
<body>
<div id=”main”>
  <h1></h1>
  <ul id=”numbers”>
  </ul>
</div>
<script src=”http://code.jquery.com/jquery-1.7.1.min.js”></script> 
<script>
function fib() {
  var int1 = 0,
  int2 = 1,
  int3,
  sequence = “<li>0</li><li>1</li>”;
  for ( var i = 3; i <= 100; i++ ) {
    int3 = int1 + int2;
    int1 = int2;
    int2 = int3;
    sequence += “<li>”+int3+”</li>”
  }
  $( “#numbers” ).append( sequence ).show( 500 );
}
function success() {
  $( “h1” ).text( “Fibonacci!” );
}
function failure() {
  $ (“h1” ).text( “No numbers?” );
}
$(function(){
  $.when( fib() )
    .done( success )
    .fail( failure );
});
</script> 
</body>
</html>

Code snippet is from basic-deferred.txt

If you’ve been paying attention, you’ll remember that if a function is passed to $.when and it isn’t a Deferred object, it’s treated as a resolved Deferred and the Deferred.done method is called. In this case, the Deferred.fail method will never fire.

So, although it’s valid, and will work basically as expected and illustrates the basic pattern, it’s missing the star of the show. The next code sample shows fib redefined to leverage the Deferred object. The function now returns Deferred.promise. The logic of the previous fib function is passed into $.Deferred as an argument.

It’s important to note the resolution of the promise as a callback to $.show. This is an important pattern discussed in depth in the next section.

image
 <!doctype html>
<html>
<head>
<meta charset=”utf-8”>
</head>
<body>
<div id=”main”>
  <h1></h1>
  <ul id=”numbers”>
  </ul>
</div>
<script src=”http://code.jquery.com/jquery-1.7.1.min.js”></script> 
<script>
function fib() {
  return $.Deferred(function() {
    var int1 = 0,
    int2 = 1,
    int3, sequence = “<li>0</li><li>1</li>”;
    for (var i = 3; i <= 100; i++) {
      int3 = int1 + int2;
      int1 = int2;
      int2 = int3;
      sequence += “<li>” + int3 + “</li>”
     }
     $(“#numbers”)
       .append(sequence)
       .show(1000, this.resolve);
    }).promise();
}
 
function success() {
  $( “h1” ).text( “Fibonacci!” );
}
function failure() {
  $ (“h1” ).text( “No numbers?” );
}
$(function(){
  $.when( fib() )
    .done( success )
    .fail( failure );
});
</script> 
</body>
</html>

Code snippet is from proper-deferred.txt

Although this is a simple example, it illustrates the power of the Deferred pattern. Callbacks in jQuery are a common source of tight coupling. They’re often defined in place, as anonymous functions with too little attention paid to abstraction.

The following animation example presents a clear illustration of how Deferred can untangle your program logic, allowing for greater code reuse and a cleaner overall architecture. Without Deferreds, callback logic for animations is tied directly to the animation call as an optional complete argument. complete is defined as a function that will be fired when the animation ends. An example of the traditional manner of doing this is shown in this first code sample:

image
 <!doctype html>
<html>
<head>
<meta charset=”utf-8”>
</head>
<body>
<div id=”main”>
 <div id=”statusbar” style=”display:none”>
 </div>
</div>
<script src=”http://code.jquery.com/jquery-1.7.1.min.js”></script> 
<script>
function updateStatus() {
  var $update = $(“<ul />”),
  $statusbar = $(“#statusbar”),
  html = []; // text buffer
  for ( var i = 0, test = 20; i < test; i++ ) { 
    html.push( “<li>status update</li>”);
  }
  html = html.join(“
”); // buffer -> string
  $update.append(html);
  $statusbar.append($update);
  $statusbar.slideDown(5000, function() {
    console.log(“animation is done! On to the next operation”);
  });
}
 
$(function(){
  updateStatus();
});
</script> 
</body>
</html>

Code snippet is from tight-callbacks.txt

Though there’s a simple console.log in the complete argument in this example, far more complicated application data is commonly packed into similar complete callbacks.

This might be acceptable if updateStatus will only ever be used with the anonymous callback function. If it needs to be matched with other functions, it’s a different story. Pulling the logic from a callback function buried deep inside updateStatus allows for more flexibility in terms of code reuse.

Alternatively, to solve this, you could add a callback function as an argument to updateStatus, but using Deferred and returning a resolved promise is far more flexible. The following code sample shows how updateStatus could be rewritten to leverage Deferreds:

image
 function updateStatus() {
  return $.Deferred(function() {
    var $update = $(“<ul />”),
    $statusbar = $(“#statusbar”),
    html = []; // text buffer
    for ( var i = 0, test = 20; i < test; i++ ) { 
      html.push( “<li>status update</li>”);
    }
    html = html.join(“
”); // buffer -> string
    $update.append(html);
    $statusbar.append($update);
    $statusbar.slideDown(1000, this.resolve);
  }).promise()
}

Code snippet is from decoupling.txt

With just the simple application of a Deferred, updateStatus is now much more flexible. Instead of being tied to a single callback, you can now use that same piece of code in several different flows. The upcoming code block shows several ways in which it could be used to take advantage of Deferreds.

The example contains three callback functions. The first is equivalent to the original anonymous functions passed in as a callback in the first example. The second, alternativeCallback, represents a different path to follow after the animation completes. If the same animation is running on a second page, a different piece of markup will have to be updated. The third, happyBirthday, represents a function to be called in a special case where a specific UI update would be required, a “HAPPY BIRTHDAY” message indicator, for example. Three uses of $.when follow. The first replicates the original case with a single callback function. The second shows the alternative callback. The third shows multiple callbacks.

image
 function callback(){
  console.log(“The animation is done. On to the next operation”);
}
function alternativeCallback(){
  console.log(“The animation is done. Let's follow a different path.”);
}
function specialCase(){
  console.log(“This is a special case. Let's do a special UI update.”);
}  
 
$.when( updateStatus() )
  .done( callback );
 
//an alternative callback
 
$.when( updateStatus() )
  .done( alternativeCallback );
 
//multiple callbacks 
 
$.when( updateStatus() )
  .done( 
     [ callback, 
       specialCase ] 
   );

Code snippet is from decoupled-callbacks.txt

As you can see, the code nicely decoupled the callback logic from the animation buried in the function body. This allows for greater code reuse and presents a much clearer pattern for any other developers on the project to grasp. No one even needs to read updateStatus to know how the application flows. It’s all laid out in (nearly) plain English.

Deferred.then Syntactic Sugar for Deferred.fail and Deferred.done

As with aliases for $.ajax like $.get and $.post, jQuery provides a convenient alias for the core Deferred objects: Deferred.then. Deferred.then accepts two arguments, one for resolved promises and the other for rejected promises. Like the functions it maps to, Deferred.done and Deferred.fail, the arguments for Deferred.then can either be individual functions or an array of functions.

The following code sample shows the original Deferred example from earlier in the chapter rewritten to use Deferred.then.

image
 <!doctype html>
<html>
<head>
<meta charset=”utf-8”>
</head>
<body>
<div id=”main”>
  <h1></h1>
  <ul id=”numbers”>
  </ul>
</div>
<script src=”http://code.jquery.com/jquery-1.7.1.min.js”></script> 
<script>
function fib() {
  return $.Deferred(function() {
    var int1 = 0,
    int2 = 1,
    int3, sequence = “<li>0</li><li>1</li>”;
    for (var i = 3; i <= 100; i++) {
      int3 = int1 + int2;
      int1 = int2;
      int2 = int3;
      sequence += “<li>” + int3 + “</li>”
     }
     $(“#numbers”)
       .append(sequence)
       .show(1000, this.resolve);
    }).promise();
}
 
function success() {
  $( “h1” ).text( “Fibonacci!” );
}
function failure() {
  $ (“h1” ).text( “No numbers?” );
}
$(function(){
  $.when( fib() )
    .then( success, failure );
});
</script> 
</body>
</html>

Code snippet is from deferred-then.txt

Because Deferred methods are chainable, Deferred.then can be combined with Deferred.done, Deferred.fail, or even additional Deferred.then calls.

Using the Deferred Aspects of $.ajax

As was previously mentioned, $.ajax is a Deferred object and the success, error, and complete callback methods are analogous to Deferred.done, Deferred.fail, and Deferred.always, respectively. The following code shows a typical $.get request:

image
 $.get(“/status/json/”,
  function( data ) {
    var $update = $( “<ul />” ),
    $statusbar = $( “#statusbar” ),
    html = “”,
    statusMessages = data.statusMessages;
    for ( var i = 0, test = statusMessages.length; i < test; i++ ) {
      html += “<li>” + status[i] + “</li>”;
    }
    $update.append(html);
    $statusbar.append($update);
    $statusbar.slideDown(1000);
  }
);

Code snippet is from non-deferred-ajax.txt

The next code block shows the same Ajax request, written using Deferreds. It’s important to note that the arguments passed to updateStatus are the same that would be passed to the callback function of a typical Ajax request. It includes the data, a text string indicating the status of the request, and the jQuery XMLHttpRequest (jqXHR) object. Also introduced in jQuery 1.5 as part of the $.ajax rewrite, the jqXHR object is an enhanced version of the standard XMLHttpRequest object. It comes complete with all of the Deferred methods, which means anything that you learn about the standard Deferred object is similarly available on all $.ajax requests.

image
 function getStatus() {
  return $.ajax({
    url : “/status/json/”,
    dataType : “json” 
  })
}
 
function updateStatus( data ) {
  var $update = $( “<ul />” ),
  $statusbar = $( “#statusbar” ),
  html = “”,
  statusMessages = data.statusMessages;
  for ( var i = 0, test = statusMessages.length; i < test; i++ ) {
    html += “<li>” + statusMessages[i] + “</li>”;
  }
  $update.append( html );
  $statusbar.append( $update );
  $statusbar.slideDown( 1000 );
}
$.when( getStatus() )
    .done( updateStatus );

Code snippet is from deferred-ajax.txt

On the surface, the preceding code may not seem like much of an improvement over the traditional callback method. It’s a little bit longer and it’s a little less free-flowing than the traditional inline callback used in jQuery Ajax requests. Beyond the surface, it’s useful to note that once again, the callback logic is decoupled from the specific Ajax request. This immediately makes that getStatus function more flexible. Additionally, as with any Deferred object, multiple $.ajax requests can be passed into $.when and multiple callbacks can be chained to respond to changes in the promise status, so the possibilities are greatly expanded. The next example presents an exaggerated, but hopefully illustrative example.

image
 $.when(
  $.post(“/echo/json”, 
    function() {
      console.log(“1”)
    }
   ), 
   $.post(“/echo/json”, 
     function() {
       console.log(“2”)
     }
  ), 
  $.post(“/echo/json”, 
    function() {
      console.log(“3”)
     }
   )
).then([
  function() {
    console.log(“4”)
  },
  function() {
    console.log(“5”)
  },
  function() {
    console.log(“6”)
  }
]).then([
  function() {
    console.log(“7”)
  },
  function() {
    console.log(“8”)
  },
  function() {
    console.log(“9”)}
]).then([
  function() {
    console.log(“10”)
  },
  function() {
    console.log(“11”)
  },
  function() {
    console.log(“12”)}
]).done(
  function() {
    console.log(“Electric Company!”)
  }
);

Code snippet is from multiple-callbacks.txt

Execute a Function No Matter What the Promise Resolution Is with Deferred.always

Oftentimes, you want a function to be called no matter what the promise resolution is. This is analogous to the complete callback, which fires on any resolution of an $.ajax request. In the world of Deferred, the method to use is Deferred.always. Like the rest of the Deferred methods, Deferred.always takes a single function or an array of functions to fire whenever a promise is resolved or rejected. The following code shows a simplified example that changes the “last updated” indicator in a mail application.

image
 $.when(
  $.ajax( “/get/mail/” )
).done(
  newMessages, 
  updateMessageList, 
   updateUnreadIndicator
).fail(
  noMessages
).always(
  function() {
    var date = new Date();
    $( “#lastUpdated” ).html( “<strong>Folder Updated</strong>: “ 
      + date.toDateString() 
      + “ at “ 
      + date.toTimeString()
    );
  }
)

Code snippet is from always.txt

Chaining and Filtering Deferreds with Deferred.pipe

Deferred.pipe, introduced in jQuery 1.6, provides a method to filter and further chain Deferreds. A common use case utilizes the ability to chain Deferreds to create an animation queue. The following code shows a simplified example that uses a chained animation used to manage the build out of the components of a web application. Once the animation queue is complete, the promise is automatically resolved and the done method is fired.

image
 function buildpage() {
  return $.Deferred(function( dfd ) {
    dfd.pipe(function() {
        return $( 'header' ).fadeIn();
    })
    .pipe(function() {
        return $( '#main' ).fadeIn();
    })
    .pipe(function() {
        return $( 'footer' ).fadeIn();
    })
  }).resolve();
}
$.when( buildpage() )
  .done(function() {
    console.log('done')
  }
);

Code snippet is from deferred-pipe-animation.txt

Deferred.pipe allows for more than just convenient chaining; it provides a very handy way to filter Deferreds based on secondary criteria. Deferred.pipe accepts three arguments: a doneFilter, a failFilter, and a progressFilter. The concept of progress is covered in a later section. For now, you focus on filtering standard Deferred objects.

The following code shows an example of filtering an $.ajax response based on component data. This example expands on the skeleton mail update application you saw previously. In this example, assume the mail service always returns a successful HTTP response in the 200 range, even when there’s no mail. Therefore, the $.ajax success function always runs. With Deferred.pipe, you can examine the data provided by the service and test whether or not there are messages in the data object. If there are messages, the response is accepted as a valid, successful response and the data is passed along to the Deferred.done methods. If there are no messages, you reject the promise with Deferred.reject. This sets off the Deferred.fail methods.

image
 $.when(
  $.ajax( “/get/mail/” )
).pipe(
  function( data ) {
    if ( data.messages.length > 0 ) {
      return data
    } else {
      return $.Deferred().reject();
    }
  }
).done(
  newMessages, 
  updateMessageList, 
  updateUnreadIndicator
).fail(
  noMessages
).always(
  function() {
    var date = new Date();
      $(“#lastUpdated”).html(“<strong>Folder Updated</strong>: “ 
        + date.toDateString() 
        + “ at “ 
        + date.toTimeString()
      );
    }
  );

Code snippet is from advanced-pipe.txt

Resolving and Rejecting Promises

As you’ve seen in passing throughout this chapter, you occasionally need to manually resolve or reject promises. You’ve already encountered the two most common methods to do this: Deferred.resolve and Deferred.reject. What you haven’t seen is the optional args argument in use. Both of these methods accept an optional argument that will, in turn, be passed to the Deferred.done or Deferred.fail methods depending on the resolution of the promise.

The following example shows a simplified illustration of these optional arguments. Returning to the mail example, the code snippet creates an updated date string to represent the time of the mail update. This string is passed along to the Deferred.fail and Deferred.done methods. Additionally, the number of messages is passed to Deferred.done to update the #message paragraph with the current number of new messages retrieved.

image
 function newMessages( obj ) {
  $( “#message” ).text(“you updated at “ 
    + obj.date 
    + “  and have “ 
    + obj.number 
    + “ new messages”
    )
}
function noMessages( obj ) {
  $( “#message” ).text(“you updated at “ 
      + obj.date 
      + “ and have no new messages”
    )
}
$.when(
  $.ajax( “/get/mail/” )
).pipe(
  function( data ) {
    var date = new Date();
    date = date.toDateString() + “ at “ + date.toTimeString();
    if ( data.messages.length > 0 ) {
      return $.Deferred().resolve({
        date: date,
        number: data.messages.length
      });
    } else {
      return $.Deferred().reject({
        date: date
    });
  }
}
 
).done(
  newMessages
).fail(
  noMessages
);

Code snippet is from resolving-and-rejecting.txt

Additionally, the related methods Deferred.rejectWith() and Deferred.resolveWith() are available to allow you to set a specified this context as the first argument when resolving or rejecting a Deferred.

Tracking Progress with Deferred.progress and Deferred.notify

Added in jQuery 1.7, the Deferred.progress and Deferred.notify methods combine to allow for in-process updating of long-running functions.

The basic setup is simple. At different points in your application, you set notify methods that are designed to fire at specific points in an application or in a long-running method. Deferred.notify accepts an optional argument, which will be passed along to the Deferred.progress callback. The related function Deferred.notifyWith accepts a context argument indicating the desired this context for the Deferred.progress callback. The Deferred.progress callback method is added to the chain. This callback method should be designed to handle whatever message was sent along via Deferred.notify or Deferred.notifyWith.

In the simple example that follows, the function longRunning is a Deferred that uses setTimeout to take 5000ms to resolve its promise. Before the timer is started, there’s a string notification sent out. The progress function accepts that argument and inserts the update text into the DOM. After the process is finished, you notify again that the process is complete and then manually resolve the promise.

In theory, the text update could have been handled by the Deferred.done callback, leaving the progress callback to handle just the original notification. There’s just a nice symmetry to using Deferred.notify at both ends of the process. Also, there’s always a case to be made for keeping repetition of code down to a minimum. So it just makes sense to keep all of the notifications bound to progress.

image
 var longRunning = function() {
  return $.Deferred(function(dfd) {
    dfd.notify( “operation started” )
    var callback = function() {
      dfd.notify( “operation finished” );
      dfd.resolve();
    }
    setTimeout( callback, 5000 );
  }).promise();
}
longRunning().progress(
  function( notification ) {
    $( “#notifier” ).text( notification ).fadeIn( 500 );
}).done(function() {
  $( “#notifier” ).css({
    “color” : “green”,
    “font-weight” : “bold”
  })
});

Code snippet is from deferred-progress.txt

Debugging with Deferred.state

If you ever find the need to debug Deferred resolution (and you will if you ever get deep into using Deferreds), you’ll be taking advantage of Deferred.state.

A simple utility function, Deferred.state returns a string value representing the current state of a Deferred. The three return values are “pending,” “resolved,” and “rejected.”

Table 13-1 defines the three states.

TABLE 13-1 Potential Deferred States

STATE DEFINITION
pending The Deferred object is not yet in a completed state.
resolved The Deferred object is in the resolved state, meaning that the deferred.resolve() method has been called and the Deferred’s done callback methods have fired.
rejected The Deferred object is in the resolved state, meaning that the deferred.reject() method has been called and the Deferred’s fail callback methods have fired.

The following example shows Deferred.state calls sprinkled throughout a short Deferred chain based on the long-running function example from the previous section.

image
 var longRunning = function() {
  return $.Deferred(function( dfd ) {
    dfd.notify( “operation started” );
    console.log( dfd.state );
    var callback = function() {
      dfd.notify( “operation finished” );
      dfd.resolve();
    }
    setTimeout( callback, 5000 );
  }).promise();
}
 
longRunning().progress(
  function( notification ) {
    console.log( dfd.state );
    $( “#notifier” ).text( notification ).fadeIn(500);
}).done(function() {
  console.log( dfd.state );
  $( “#notifier” ).css({
    “color” : “green”,
    “font-weight” : “bold”
  })
});

Code snippet is from deferred-state.txt

SUMMARY

You should now have a solid understanding of the possibilities and power of jQuery’s Deferred object and its many available methods.

Throughout the chapter, you’ve seen examples of Deferred being used to pull application logic outside of function bodies and into the more maintainable, flexible structure provided by methods like Deferred.when, Deferred.then, and Deferred.done.

You also learned about creating, resolving, and rejecting promises manually, a vital piece in unlocking the power of Deferred.

Additionally, you had some exposure to more obscure options like the ability to notify on the progress of a Deferred and the ins and outs of debugging with Deferred.state.

Once your head is truly wrapped around Deferreds, you’ll start looking at your current and past codebases with the goal of refactoring that old code to leverage the power and structure provided by Deferred. The flexibility and clarity it brings to your application code makes it one of the most important recent features added to the library.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.118.142.166