Feb 28, 2012

jQuery Deferred object

You can create a Deferred object like this

var dfd = $.Deferred()

As of now this goes to the pending state (or unfulfilled)

you can add as many number of then(),done(),fail() which is kindof event. These are callbacks which are called once deferred object is resolved or rejected. So you can consider these as listener which can be triggered by calling resolve or reject.
 

  dfd.done(function(){
   alert("deferred object got resolved");
  })
  
  dfd.done(function(){
   alert("I am also notified that the deferred object got resolved");
  })
  
  dfd.fail(function(){
   alert("deferred object got rejected");
  })
  
  dfd.then(function(){
   alert("deferred object got resolved");
  },function(){
   alert("deferred object got rejected");
  }
  )

Once you resolve or reject deferred object it goes into resolved (fulfilled) or rejected (failed) state. When the Deferred is resolved, any doneCallbacks added by done or then are called in the order they were added. Similarly for reject, it call fail or fail part of then.
 
  dfd.resolve();
  dfd.reject();

State 
Deferred object has state which you can get from dfd.isResolved() or dfd.isRejected(). The state is persistent, which means once resolved or rejected it will maintain its state forever. After this any then/done/fail called will be executed immediately.

Promise
This object provides a subset of the methods of the Deferred object (then, done, fail, always, pipe. isResolved, and isRejected) to prevent users from changing the state of the Deferred.

dfd.promise();

If you return deferred object it gives the caller access to resolve or reject directly. So if you don't want caller to have that access then you can return promise object.

Real word example

1. jQuery ajax has been implement using deferred. Now when you do $.get("jQuery-Deferred.html"); it returns Promise object which is read only (It exposes only the Deferred methods needed to attach additional handlers or determine the state, but not ones that change the state )
 
  var req = $.get("jQuery-Deferred.html");
  req.done(function( response ){
     alert("ajax call done");
   });
  req.fail(function( response ){
     alert("ajax call failed");
   }); 

2. Convenient Wait function
 
 function timedMsg()
 {
  wait(1).done(function(){alert("I am displaying after 1 second");});
  wait(11).fail(function(msg){alert(msg);});
 }

 function wait(time) 
 {
  var dfd = $.Deferred();
  if(time < 10){
   setTimeout(dfd.resolve,time*1000);
  }
  else
  {
   dfd.reject("User will not like more than 10 second of wait time.");
  }
  //By returning promise I make sure that the caller doesn't have ability to reject or resolve.
  return dfd.promise();
 }


3. Efficient ajax call
 
 function someCostlyTaskLikeAjax(url) 
 {
  alert("someCostlyTask is called");
  var time = 1;
  var dfd = $.Deferred();
  setTimeout(dfd.resolve("I am resolved"),time*1000);
  return dfd.promise();
 }
 
 function cachingDeferredObject(){
  
  var cache = {};
  
  function fetch_some_object(key){
   if (cache[key]) { 
    alert("I am coming from cache - " + cache[key]);
    return cache[key]; 
    }
    
   return cache[key] = someCostlyTaskLikeAjax(key).done(function(msg){
    //cache = msg;
    alert("From done handler -" + msg);
    return msg;
   });
  }
  
  $.when(fetch_some_object("someurl")).done(function(a){
   alert("1St call - " + a);
  })
  
  $.when(fetch_some_object("someurl")).done(function(a){
   alert("2nd call -" + a);
  })
  
 }

No comments:

Post a Comment