Skip to content
briancavalier edited this page Sep 22, 2011 · 16 revisions

when.defer()

You can use when.defer() to create a deferred object that has a promise for a value that will become available at some point in the future.

function loadImage (src) {
	var deferred = when.defer(),
		img = document.createElement('img');
	img.onload = function () { 
		deferred.resolve(img); 
	};
	img.onerror = function () { 
		deferred.reject(new Error('Image not found: ' + src));
	};
	img.src = src;

	// Return only the promise, so that the caller cannot
	// resolve, reject, or otherwise muck with the original deferred.
	return deferred.promise;
}

// example usage:
loadImage('http://google.com/favicon.ico').then(
	function gotIt(img) {
		document.body.appendChild(img);
	},
	function doh(err) {
		document.body.appendChild(document.createTextNode(err));
	}
).then(
	function shout(img) {
		alert('see my new ' + img.src + '?');
	}
);

when.all()

Using the same loadImage function, we can load multiple images and return a promise that resolves only when all images have loaded.

function loadImages(srcs) {
	// srcs = array of image src urls

	// Array to hold deferred for each image being loaded
	var deferreds = [];

	// Call loadImage for each src, and push the returned deferred
	// onto the deferreds array
	for(var i = 0, len = srcs.length; i < len; i++) {
		deferreds.push(loadImage(srcs[i]));
		
		// NOTE: We could push only the promise, but since this array never
		// leaves the loadImages function, it's ok to push the whole
		// deferred.  No one can gain access to them.
		// However, if this array were exposed (e.g. via return value),
		// it would be better to push only the promise.
	}

	// Return a new promise that will resolve only when all the
	// promises in deferreds have resolved.
	// NOTE: when.all returns only a promise, not a deferred, so
	// this is safe to expose to the caller.
	return when.all(deferreds);
}

// Do something fancy after the images are loaded
loadImages(imageSrcArray).then(
	function gotEm(imageArray) {
		doFancyStuffWithImages(imageArray);
		return imageArray.length;
	},
	function doh(err) {
		handleError(err);
	}
).then(
    function shout (count) {
		// This will happen after gotEm() and count is the value
		// returned by gotEm()
        alert('see my new ' + count + ' images?');
    }
);

// Or, equivalently using when() instead of .then()
when(loadImages(imageSrcArray),
	function gotEm(imageArray) {
		doFancyStuffWithImages(imageArray);
		return imageArray.length;
	},
	function doh(err) {
		handleError(err);
	}
).then(
    function shout (count) {
		// This will happen after gotEm() and count is the value
		// returned by gotEm()
        alert('see my new ' + count + ' images?');
    }
);

Clone this wiki locally