Treehouse

Dojo DeferredList

By on  

Deferreds are all the rage in the JavaScript community these days and who can argue?  Deferreds, an object representing an asynchronous action, make working with AJAX requests incredibly easy -- no callback hell, no problem passing request information around.  What if you want to work with multiple Deferreds though?   For example, say you want to execute functionality once multiple AJAX requests complete.  The Dojo Toolkit has you covered with dojo/DeferredList, a resource whose API mirrors a single Deferred object but is capable of handling multiple Deferreds.

Using Deferreds

Dojo returns Deferred objects from many operations, including animation and XHR requests.  With the Deferred object, you can use the then property to react to the response once the async interaction is completed:

// A very basic usage of dojo/request
request("service.php?id=someid").then(function(response) {
	console.log("request result is:", response);
});

The example above shows a basic AJAX request and handling of the resulting Deferred.  Easy, right?  But what if you want an action to execute only after multiple Deferreds have resolved?

Using dojo/DeferredList

The DeferredList is a manager for multiple Deferreds, making handling multiple Deferreds a breeze:

// Require the Dojo dependencies
require(["dojo/request", "dojo/DeferredList"], function(request, DeferredList) {
	console.log("Request loaded!", request);

	// Request 1
	var promise1 = request("/endpoint/1").then(function(response) {
		console.log("request 1 result", response);
	});

	// Request 2
	var promise2 = request("/endpoint/2").then(function(response) {
		console.log("request 2 result", response);
	});

	// Create a DeferredList to manage both of them
	var list = new DeferredList([promise1, promise2]);
	// When they're both resolved...
	list.then(function(result) {
		// result is:  [Array[2], Array[2]]
		// result item[0] is the result of each request

		// Do something!
		
	});
});

The example above represents all roses:  all successful Deferreds.  What if a Deferred fails;  a 404 error, request timeout, or a Deferred rejection?  A little validation cures all that:

// Require the Dojo dependencies
require(["dojo/request", "dojo/DeferredList"], function(request, DeferredList) {
	console.log("Request loaded!", request);

	// Request 1
	var promise1 = request("/endpoint/1").then(function(response) {
		console.log("request 1 result", response);
	});

	// Request 2
	var promise2 = request("/endpoint/2").then(function(response) {
		console.log("request 2 result", response);
	});

	// Request 3:  A request that will fail...
	var promise3 = request("/endpoint/noexist").then(function(response) {
		console.log("request 3 result (fail)", response);
	});

	// Create a DeferredList to manage both of them
	var list = new DeferredList([promise1, promise2, promise3]);
	// When they're both resolved...
	list.then(function(result) {
		if(request[0][0] && request[1][0] && request[2][0]) { // request[2][0] is false
			// Success!
		}
		else {
			// React to a failure
		}
	});
});

If the promise for a given Deferreds returns false, you know the request (or async action) failed.  The second argument returned by the Deferred provides information about the request and why it failed:

{
	"message": "Unable to load noexist.php status: 404",
	"response": {
		"url": "/endpoint/noexist",
		"options": {
			"headers":{}
		},
		"xhr": {
			"statusText": "Not Found",
			"status": 404,
			"response": "{404 page html}"}
		}
}

The example here is oversimplified.  One realistic example is the one I used to create the dojox/mobile TweetView example, sending multiple JSONP requests (Twitter profile and Twitter timeline list) for a client-side Twitter widget.  The dojo/DeferredList resource makes handling multiple asynchronous actions easy and enjoyable.  Just another reasons to use the Dojo Toolkit in your next web application!

ydkjs-4.png

Recent Features

  • An Interview with Eric Meyer
  • 9 Mind-Blowing WebGL Demos

    As much as developers now loathe Flash, we're still playing a bit of catch up to natively duplicate the animation capabilities that Adobe's old technology provided us.  Of course we have canvas, an awesome technology, one which I highlighted

  • 5 HTML5 APIs You Didn’t Know Existed

    When you say or read "HTML5", you half expect exotic dancers and unicorns to walk into the room to the tune of "I'm Sexy and I Know It."  Can you blame us though?  We watched the fundamental APIs stagnate for...

Incredible Demos

  • NSFW Blocker Using MooTools and CSS

    One of my guilty pleasures is scoping out the latest celebrity gossip from PerezHilton.com, DListed.com, and JoBlo.com. Unfortunately, these sites occasionally post NSFW pictures which makes checking these sites on lunch a huge gamble -- a trip to HR's office...

  • MooTools PulseFade Plugin

    I was recently driven to create a MooTools plugin that would take an element and fade it to a min from a max for a given number of times. Here's the result of my Moo-foolery. I'm satisfied with the effect...

  • iPhone Click Effect Using MooTools or jQuery

    One thing I love about love about Safari on the iPhone is that Safari provides a darkened background effect when you click a link. It's the most subtle of details but just enforces than an action is taking place....

Discussion

  1. Be sure to check out dojo/promise/all in 1.8:

    all([def1, def2]).then(function(results){
        // results[0], results[1]
    });
    
    • I like that DeferredList is backward-compatible and better documented :)

  2. Markus

    jQuery’s $.when() does the same job, but the api looks more intuitiv

  3. Cesar

    Is there any way to learn Dojo that isn’t a pain in the back? I’m trying and I have quite a bit of experience on other libraries, but Dojo does things in such a crazy way (or the docs are really bad at explaining things), for example, I still can’t understand why make such a huge change just to avoid global scope, after all, if you just use Dojo, you won’t have name conflicts (and even then you can just use dojo.blahblah).

    Sorry if this looks like I’m against Dojo, I’m not, in fact I’m trying to migrate from Mootools, but besides being “the more correct way to code” (which many have claimed and I still think it’s quite subjective) I’m starting to think there isn’t a worthy reason to go through all the pain of learning Dojo, yes, and I will say it again it’s a pain even with the good will to learn it, I’m having such a heavy complain because I didn’t have this problem moving from JQuery to Mootools which, both are a “import/customize the file, use whatever you need, learn as you need”, you don’t have to learn to code again, you just have to use the libraries (though Mootools it’s more suitable for large projects because it’s more organized).

    I’ve been following your blog since quite some time and I would like to know your opinion about this (and a possible solution).

    • Skullcap

      I agree with Cesar. I have been trying to be efficient at working with dojo and dijit for 6 months (!)… and I still feel like an idiot with it. Maybe I am an idiot, I have never had this problem with any other framework/toolkit/api… Dojo leaves me scratching my head every fricking day. Dojo.core seems elegant, logical and straight forward to use. But dijit!! Oh my. Oh my oh my. I want to curl up into a ball and suck my thumb whenever I have to work on widgets or even worse, style my widgets (sadly, this is daily for the past few months; my thumb is quite raw by now). Look at me, I am ranting instead of working on my widgets.

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!

Use Code Editor