Transliteration of Promises to Callbacks

1 minute read

Sometimes when you see enough examples, things just click. I have multiple examples that show you an implementation (before) and then an alternate implementation using promises (after). Note: Keep in mind that different libraries have different implementations but these should all still be relevant;

Here are some before and afters


before

getUser('washington', function(err, user){
  if (!err) {
    // do something with user
  } else {
    // handle the error
  }
});

after

getUser('washington').then(function onFulfilled (user){
  // do something with user
}, function onRejected (err){
  // handle the error
});


before

var user = getUser('washington');
var name = user.name;

after

getUser('washington').then(function(user){
  return user.name
});


before

var user = getUser('washington');
if (!user) {
  throw new Error('no user!');
}
var name = user.name;

after

getUser('washington').then(function (user){
  if (!user){
    throw new Error('no user!');
  }
  return user.name;
});


before

try {
  deliverTweetTo(tweet, 'washington');
} catch (error) {
  handleError(error);
}

after

deliverTweetTo(tweet, 'washington')
.then(undefined, handleError);

before (callbacks)

getUser('washington', function(user){
  getNewTweets(user, function (tweets){
    updatePage(tweets);
  });
});

after (promises)

getUser('washington')
.then(getNewTweets)
.then(updatePage);

before

getUser('washington', function(err, user){
  if (err){
    handleError(err);
  } else {
    getNewTweets(user, function(err, tweets){
      if (err){
        handleError(err);
      } else {
        updatePage(tweets, function(err){
          if (err){
            handleError(err);
          }
        });
      }
    });
  }
});

after

getUser('washington')
.then(getNewTweets)
.then(updatePage)
.then(undefined, handleError);

Another example with Mongoose

userSchema.statics.checkAuthentication = function(options, cb) {
  var username = options.username;
  var password = options.password;

  var Promise = require('bluebird');
  // bind to have an object along the chain of promises
  Promise.resolve(User.findOne({username:username}).exec()).bind({})
  .then(function(user){
    this.user = user;
    // call comparePassword with user as the context of this vs global
    return Promise.promisify(user.comparePassword).call(user, password);
  })
  .then(function(match){
    // check password match
    if (match) {
      cb(null, this.user);
    } else {
      throw new Error("invalid username or password");
    }
  })
  .then(undefined, function(err){
    cb(err);
  });
};