jQuery Promises, Deferred & WebWorkers
Written by Ian Elliot   
Friday, 21 September 2012
Article Index
jQuery Promises, Deferred & WebWorkers
Web Worker Based Promises

It is fairly easy to consume promises returned by asynchronous functions that other programmers have put together for you. It is only a little more difficult to use promises and within your own asynchronous functions. Let's see how it works.

 

justjquery

Just jQuery

Asynchonous jQuery

  • Part I   Promises & Deferred - the consumer
  • Part II  Promises, Deferred & WebWorkers  - the producer

The key to understanding how to make use of jQuery's promise object is to realize that it is for the consumer of asynchronous functions. If you don't understand the promise object then make sure to read jQuery, Promises & Deferred

The producer of asychronous functions has to learn a little more about the Deferred object.which is a Promise object with some additional methods that can be used to change the state of the Promise object. Notice that the consumer or end user of the Promise object should never really need to change its state - only the producer or owner of the Promise object needs to change its state.

The Deferred Object

You can think of a Deferred object as containing a Promise object inside it. If you recall a Promise object is in one of three states - pending, resolved or failed. The Promise object starts out in the pending state and the Deferred object has two methods to change its state to resolved or failed - resolve() and reject().

If you call the resolve method e.g.

myDeferred.resolve(args);

then the onComplete function is called with the specified arguments as soon as one is defined. That is any functions added using the done method or then are called in the order they were added with the same arguments. If a function is added after you have use resolve then it is called immediately with the same arguments.

The reject method works in the same way but it calls the onError functions you have defined. Again you can specify the arguments to be passed and any functions added after you call reject are executed immediately. 

There is also a notify method that can be called to execute any progress reporting function that the user might have defined. This works in the same way as the other two methods but for simplicity we will ignore it for the moment.

A Timer Promise

As an example to get us started let's take a look at a true asynchronous method. In this case we don't involve another thread or anything complicated we have a simple asynchronous task that takes a long time but which generates and event or an interrupt went it is complete.

As an example of an asynchronous task that fires an event when it is complete the simplest thing to use is a timer. We can essentially wrap the timer with a promise object.

The setTimout function will execute any function after a specified time in millisecond. Notice that this is non-blocking i.e. it doesn't keep the UI thread for the time period so it is ideal for our purpose.

We can easily implement a timeout function that returns a Promise object which the user can set and onComplete function which will be called when the time in milliseconds is up:

function timeout(time) {

The first thing we have to do is create a Deferred object that we can return:

var deferred = $.Deferred();

Next we set up the call to setTimeout.

What do you think has to happen when the time is up?

The function will have returned the Deferred object we set well before the time is up and the user might have set an onComplete function using it. So what we have to do is to use the resolve method to execute any onComplete functions.

This seems a bit odd at first but keep in mind that this next function will only run when the time is up:

setTimeout(
 function () {
   deferred.resolve(time);
 }, time);

Notice that we supply the onComplete function with the time delay stored in time. We don't have to return a value but it is customary to do so. You can also return any number of other parameters and the onComplete function can process them or ignore them as you please.

Finally we need to return the Deferred object so that the user of the timeout function can set onComplete. We could return the Deferred object but this would give the caller of the function the ability to modify the state of the Promise. Much better to use the Deferred object's promise method to return a true Promise object:

  return deferred.promise();
};

Putting all this together gives:

function timeout(time) {
  var deferred = $.Deferred();
  setTimeout(
     function () {
        deferred.resolve(time);
     }, time);
  return deferred.promise();
};

Now we have the timeout function how do we use it?

The answer is just like any other function that returns a Promise object.

For example:

var myPromise1 = timeout(3000);
myPromise1.then(
  function (t) {
    console.log(t);
  });

Notice that the onComplete function prints the value fo the timeout.

The code have been written in such a way as to emphasis the idea that a Promise object is returned but you could just as easily write:

timeout(3000).then(
  function (t) {
    console.log(t);
  });

 

You could include an onError and a progress function but it doesn't make sense to do so in such a simple example.

 

Banner

 

 



Last Updated ( Sunday, 09 November 2014 )
 
 

   
Copyright © 2014 i-programmer.info. All Rights Reserved.
Joomla! is Free Software released under the GNU/GPL License.