Promises as before filters

The Firebase JS library is callback-based, which feels pretty cumbersome after I got used to promises. So, the other day I wanted to have a FirebaseClient object that given a Firebase URL and credentials would give me a simple way to read and write data to it, something like this:

var data = new FirebaseClient(url, secret);

data.get('/some/path')
.then(useTheData);

data.set('/some/path', value)
.then(announceSuccess);

In Firebase you can have “public” databases that can be accessed anonymously, and “private” databases that you can still connect to anonymously, but can’t access any data before you authenticate: connection and authentication are two separate and disconnected in time steps. You can technically connect and try to access the data, but for a private database you’ll get a permission error.

So in my FirebaseClient’s get and set I would have to first ensure the authentication finished and only then try to access the data, both of which are async callback-based calls.

In synchronous worlds like Rails, you achieve this with synchronous before_filters, but this is not how it works in callback-based JS.

It turns out that it’s pretty easy to get code that is comparably clear with the synchronous before_filters if I wrap the authentication in a promise:

function FirebaseClient(url, secret) {
  var ref = new Firebase(url);
  this.authenticate = authenticate(ref, secret);
}

function authenticate(ref, secret) {
  // return a promise to authenticate
}

then make it a prerequisite in methods that need authentication finished before doing their own work:

FirebaseClient.prototype.get = function(path) {
  return this.authenticate.then(get(path));
};

function get(path) {
  // return a function which does the actual data access
}

Before being resolved, the authenticate promise will queue everything that is then()ed on it. After it’s resolved, it will just just pass through to the subsequent then() calls. Nice! :)