Thursday, September 4, 2014

Don't make promises

Wrapping promises with promises to return promises that were already promises

When I first began to understand the value that promises could be to my code, I immediately began to misuse them.  I would create a deferred and resolve it like this:

function getData() {
  var deferred = $q.defer();
  $http.get('http://some.url.com/data')
    .success(function(data) {
      deferred.resolve(data);
    })
    .error(function(data) {
      deferred.reject(data);
    });
  return deferred.promise;
}


Then it occurred to me that $http returns a promise. So the above code was equivalent to (but slower than) this:

function getData() {
  return $http.get('http://some.url.com/data');
}


That example used the Angular.js $q promise implementation, but the same code works with all of the other major promises implementations.

Dealing with callbacks

Once I figured out that I could just return the promise, I realized that the only time I needed to create promises was when I was dealing with libraries like request, nano, fs, etc. Then I discovered bluebird's promisify and promisifyAll. Bluebird's promisifyAll creates functions that return promises instead of calling callbacks for almost any library. Here is an example with request:

var Promise = require('bluebird');
var _request = require('request');
var request = Promise.promisifyAll(_request);

exports.getData() {
  return request.getAsync('http://some.url.com/data')
    .then(sanitizeData)
    .catch(logAndRethrow);
}


Don't make promises

So now there is almost no reason to make a promise. Library authors and dumb setTimeout examples aside, creating promises should be extremely rare.

No comments:

Post a Comment