Deferreds and a Better Geolocation API

Warning, this article is intended for Deferred unbelievers to convince them that Deferred objects are both easy and useful. If you’re already a Deferred object expert, you might want to skip this one.

Earlier this year I was given the opportunity to attend the jQuery Conference in San Francisco. I was delighted to go, able to finally meet some of the JavaScript greats I’d been stalking following online for years.

At first, Deferred objects sound scary. I can assure you that they’re actually incredibly easy and incredibly useful. Today we’ll go through the simple task of reworking the Geolocation API to use jQuery Deferred objects.

Here is the standard Geolocation API to retrieve the user’s current position:

When the above API is called, a prompt is shown to the user asking if they want to divulge their location information to the domain of the currently active web site. Typically this prompt is a non-blocking asynchronous operation (although not explicitly defined in the specification).

Notice that the success callback is replaced by the deferred object’s resolve method and the error callback is replaced by the reject method. All of our function arguments are removed from the API. We’re left with one simple options argument.

This allows us to do things like:

getCurrentPositionDeferred({enableHighAccuracy:true}).done(function(){// success}).fail(function(){// failure}).always(function(){// executes no matter what happens.// I've used this to hide loading messages.});// You can add an arbitrary number of// callbacks using done, fail, or always.

We could also use $.when to run code upon completion of two arbitrary and contrived operations like a Geolocation call and an Ajax request. Awesome.

To coordinate between multiple Deferred objects, use $.when:

$.when(getCurrentPositionDeferred(),$.ajax("/someUrl")).done(function(){// both the ajax call and the geolocation call have finished successfully.});

I wonder what other browser native APIs could be better served by using Deferred objects instead of function arguments.