As some of you may know, I am mainly into WPF/WCF and that sort of stuff, however I like to keep my toe in what is going on within the web world. A while ago (a year I think), I worked with a colleague who was trying to create a TPL like Task construct in JavaScript that would support typical TPL things like:
ContinueWith
Wait
Result
WhenAny
That sort of thing. I also recall he mentioned a JQuery feature called “Deferred” and “Futures”. I must confess I did not think about this much over the past year, until I overheard a new work colleague mention “Deferred” and
“Futures”, I thought mmmmm, I really need to read up on that. So I did.
There is actually quite a lot out there on this subject, so what I present here will hardly be cutting edge or novel, but if you have not heard of it before, it may at least spike your interest to learn more.
Before I show you a sample, let's talk a bit about jQuery Deferred.
In jQuery, a Deferred object is an asynchronous activity, which can signal the success or failure of itself via registered callbacks. Since jQuery 1.5, the inbuilt jQuery Ajax calls have been using Deferred objects.
You can read more about Deferred here where we can use pipeline functions such as:
which is great. It means we can compose whole pipelines of these, and only call a callback when a whole chain is “Done”, or carry on to do some other thing.
But the true power (at least in my opinion) comes from the fact that we can create $.Deferred
objects ourselves.
Here is a trivial example that does a jQuery Get call followed by a timeout. Deferred which I made up, and will only run the callback when both of these is done.
(function ($) {
doIt();
function getData() {
return $.get('/Dummy.htm');
}
function timeout(x) {
var dfd = $.Deferred();
setTimeout(function () {
dfd.resolve();
}, x);
return dfd.promise();
}
function doIt() {
$.when(getData(), timeout(2000))
.done(function (ajaxResult, timeOutResult) {
$('#mainDiv').append(
'<br/><br/>
<strong>The animation AND the AJAX request are both done!</strong>');
alert('AJax result is \r\n :' + ajaxResult);
});
}
})(jQuery);
The key parts you need to pay special attention to are:
- That we create a new Deferred object
- We resolve the Deferred object when we do the actual work
- And we return a Promise that we will do the work from the Deferred object
This is a very very simple example of using Deferred, but this could be used for all sorts of novel things, such as:
- Caching Ajax calls
- Timeouts (ha ha)
- Building complex chains of asynchronous functions
- Communication with a Web Worker
In fact, if you want to see a great TPL/Deferred discussion, you can look at these excellent links:
- http://www.scottlogic.co.uk/2011/02/web-workers-part-2-using-jquery-deferred/
- http://www.scottlogic.co.uk/2011/02/web-workers-part-3-creating-a-generic-worker/
- http://www.scottlogic.co.uk/2011/02/web-workers-part-4-wrapping-it-up/
As always, here is a small demo project (it is a VS2012 web app, just because it is easiest for me to create this type of web project):