O'Reilly

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!

O'Reilly Velocity Conference
Save 20% with discount code AFF20

Recent Features

Incredible Demos

  • Sliding Labels Using MooTools

    A week back I saw a great effect created by CSSKarma: input labels being animated horizontally. The idea is everything positive: elegant, practical, unobtrusive, and requires very little jQuery code. Luckily the effect doesn't require much MooTools code either! The HTML A...

  • Fancy Navigation with MooTools JavaScript

    Navigation menus are traditionally boring, right? Most of the time the navigation menu consists of some imagery with a corresponding mouseover image. Where's the originality? I've created a fancy navigation menu that highlights navigation items and creates a chain effect. The XHTML Just some simple...

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!

Recently on David Walsh Blog

  • Preventing Side Effects in JavaScript

    JavaScript is very dynamic these days but I still see a lot of legacy code, whether it be for optimal backward compatibility or simply that the code hasn't been maintained.  One of the practices that makes me cringe is coding that creates unwanted side effects.  What's a side...

  • Access Mac Camera by Command Line

    With all of my recent command line tutorials, I've really gotten excited about the shell's simplicity and realized the true power of using the underlying technology of pretty UIs.  Since I work from home, I spend a lot of time on video calls, so when...

  • Open Files from Command Line on OS X

    I'm as much of a fan of application UIs as anyone else but I'm finding myself working more and more from the command line lately.  Much of that is becoming obsessed with media manipulation but I'm forcing myself to use less UIs so that I...

  • Get Stock Quotes From Command Line

    When I conned my way into my first professional programming gig, I didn't really think much about money -- just that I was getting my foot in the door.  But as my career has gone on, I've been more aware of money, investing, and retirement.  I've recently...

  • Geolocation API

    One interesting aspect of web development is geolocation; where is your user viewing your website from? You can base your language locale on that data or show certain products in your store based on the user's location. Let's examine how you can...