Promises instead of callbacks

20 January 2014

A few weeks ago I built up a very simple identity map to
get rid of a bug in highlighting active links. I introduced promises in order to
leverage the fact that Ember.js blocks in model hooks until the model is
resolved (or rejected).

In this post, I am taking a step back, and converting all the ajax calls that
fetch data from and store data to the backend to use promises. I am also going
to extract the most basic adapter that exists, just to do away with the
repetition in the XHR calls. Once I have these in place, I will able able to
build nice features on top of that.

App.TheMostBasicAdapterThereIs

All calls go to the same backend and talk in json so these can be trivially
extracted:

With that out of the way, we can see where these were used, and replace
Ember.$.ajax with App.Adapter.ajax. In the process we are also going to
convert the callback-style code to use promises, a worthwhile
transformation.

Don’t call me back, promise me you’ll be there

Here is what the code for fetching all the artists from the API looks like after
applying the adapter change:

Notice that the model initially is an empty array and only when the ajax call
returns successfully does that array get filled up and the template rerendered.
Not a big deal in itself, but if in a child route we rely on the array
containing all the artists (e.g when looking up the identity map or using
modelFor), we can be bitten by the async bug. Promises to the
rescue.

As I mentioned in the identity map post, if a promise is
returned from a model hook, Ember.js will block until the promise is resolved
(or rejected). Let’s follow in Ember.js footsteps and convert the above code to
return a promise:

We wrap the promise returned from the App.Adaptar.ajax call in another promise,
which resolves with artist objects instead of the raw data that is returned by
the API. In the rejection handler, we pass along any potential error responses
by rejecting with the same error that we got.