Tag Archives: JavaScript

Always keep your (jQuery) Promises

jQuery Deferreds are a relatively new feature and can be invaluable when coordinating multiple events and handlers. They provide you with an elegant way to register one or more callbacks into callback queues, invoke them, and signal success/failure. Another advantage they have over traditional callbacks is that you can bind a new callback at any point in your code, even after the event has occurred. If the event has already occurred (i.e. the deferred has been resolved) your callback will happen immediately. Never heard of them before? Well, if you have written code similar to this:

$.ajax(...).done(function() { })

then you have already used them! The above is valid because the jqXHR object that gets returned implements the Promise interface as of jQuery 1.5.

Here’s a high level summary of how Deferreds work:

  1. Call $.Deferred with a callback taking the newly created deferred handler as the first parameter. Once the your operation has completed you call resolve() on the deferred handler.
  2. The deferred handler should return a promise by calling promise(). Think of a promise as a lightweight version of deferred. In essence it provides an immutable version of the deferred object, meaning it can query the state of the deferred handler, but it can’t modify it (for example, it can’t resolve it).
  3. Pass the promise around to any interested consumers who would like to be notified of the event’s completion (success or failure)

Remember, you can call promise.done(…) at any point in your application, even after the deferred handler has been resolved, in which case the callback will be invoked immediately. Another interesting feature is that you can also endow any object with an existing deferred’s promise by calling deferred.promise(objectInstance). Indeed, if you look at the jQuery framework’s code this is how they attach the promise methods to the jqXHR object.

As you might guess this can become pretty powerful as it allows us to express event chains in almost any way imaginable.

As a simple example, imagine you would like to submit two asynchronous requests and perform a fade out animation at the same time. Once all three have finished a fade in animation should be run. Deferreds along with jQuery’s $.when() provide an elegant mechanism to achieve this. Take the code below:

var container = $("#mycontainer");
$.when(
	function () {
		return $.Deferred(function (dfd) {
			container.fadeOut('slow', dfd.resolve);
		}).promise();
	}(),
	$.ajax({
		url: 'Path/To/My/Url/1',
		type: 'POST',
		dataType: 'json'
	}),
	$.ajax({
		url: 'Path/To/My/Url/2',
		type: 'POST',
		dataType: 'json'
	})
).done(function (x, data) {
	container.html('Your request has been processed!');
	container.fadeIn('slow');
});

As you can see we pass three promises to $.when, one for the fade out animation and two for the ajax operations.

  • The first parameter is a self executing anonymous function that creates the deferred handler and returns the promise. In $.Deferred’s callback the dfd.resolve function is passed in to fadeOut()’s callback parameter, which means that once the animation completes the deferred will be resolved.
  • With regards to the other two parameters we pass to $.when, since the result of $.ajax is a jqXHR object that implements Promise we just pass the value that’s returned as is.

Once all three have completed we replace the content of the container with a friendly message and fade it in. This is obviously a very bare-bones example, and we’ve only scratched the surface with what can be achieved with deferreds. One thing you’ll notice is that I haven’t included any error handling for the $.ajax calls. I’ll leave that as homework.

That’s it! Pretty neat, huh?

Cascading drop down plugin for jQuery

I recently wrote a jQuery plugin called jqCascade for cascading drop downs which can be found at: http://plugins.jquery.com/project/jqcascade.

It supports several chained cascade modes when a parent list changes to a “no selection” item including:
– Simply clearing the child drop downs
– Clearing the child drop downs, leaving the default selection item intact
– Clearing and disabling the child drop downs, leaving the default selection item intact
– Hiding the child drop downs

How do you use it?

        // Cascade when parent changes
        $('#myParentDropDown').cascading({
                dataUrl: 'http://localhost:31393/Home/GetJsonData/',
                parentDropDownId: 'parentDropDownDOMId',
                noSelectionValue: '0',
                noSelectionText: '[Default Selection]'
            });

The drop downs can be chained any number of ways. As always, the project can be downloaded here. Try it out and let me know what you think, and if there’s any suggestions for enhancements you would like to see in a future release let me know!