Converting Mongoose model functions to be Promise and callback friendly simultaneously

I just started using promises in one of my Node.js applications after watching the callback hell in some of the code there.

I was going to use Q but while checking the different options I stumbled upon Bluebird and I liked it.

At some time I checked how Mongoose works with promises and discovered that many functions return a promise and also the queries’ exec() returns a promise too. The Promise in Mongoose is mpromise.

However I decided to stick to a single implementation of Promise for my entire application to have something as a standard and predictable way to use “promisified” functions. And this happened to be Bluebird. It’s huge(features) and I like it!

The first thing to “clean” was a function in one of my Mongoose’s models: User.create() – a custom static function that overrides the default create function. I needed the override to be able to receive custom structured arguments and also to do some changes before the model data is saved. I changed the way I handle the create later by removing it and using pre-hooks instead but this is a good example to show and is like a repeatable template for any other function that is going to be converted the same way.

Let’s see the original Promise-free function:

userSchema.static('create', function (data, cb) {
  var user = new User({
    facebookId: data.facebookId,
    accessToken: hat(),
    name: data.name,
    photo: data.photo
  });
  return user.save(cb);
});

You can see that User.create() receives a data object literal and executes the callback cb after it’s saved.

An example usage of create will be:

User.create({
  facebookId: '68yc7j9y4f64',
  name: 'Iliyan Trifonov',
  photo:'https://...'
}, function userCreateCb (err, user) {
  if (err) {
    return console.error(err);
  }
  if (!user) {
   return console.error('User not created!');
  }
  console.info('User created successfully!', user);
});

Now let’s make User.create return a promise:

First we promisify the model with:

Promise.promisifyAll(User);
Promise.promisifyAll(User.prototype);

and then the create function will look like:

userSchema.static('create', function (data) {
  var user = new User({
    facebookId: data.facebookId,
    accessToken: hat(),
    name: data.name,
    photo: data.photo
 });
 return user.saveAsync();
});

Now we should handle the resolve and reject:

User.create({
  facebookId: '68yc7j9y4f64',
  name: 'Iliyan Trifonov',
  photo:'https://...'
}).then(function (user) {
  console.info('User created successfully!', user);
}).catch(function (err) {
  console.error('Error creating the user!', err);
});

For now I am experimenting with the then(resolveCb)/catch(errorCb) combination but it can be changed to then(resolveCb, rejectCb) or then(resolveCb)/then(null, rejectCb).

But what about the rest of the code that depends on User.create to use a callback?

Let’s add the callback argument again:

userSchema.static('create', function (data, cb) {
  var user = new User({
    facebookId: data.facebookId,
    accessToken: hat(),
    name: data.name,
    photo: data.photo
  });
  return user.saveAsync().then(function (user) {
    return cb(null, user);
  }).catch(function (err) {
    return cb(err);
  });
});

And now the create function will work with the legacy code and the new Promises code simultaneously!

 

Robomongo — shell-centric MongoDB management tool (MongoDB Admin UI)

“Robomongo — is a shell-centric cross-platform open source MongoDB management tool (i.e. Admin GUI). Robomongo embeds the same JavaScript engine that powers the MongoDB 2.2mongo shell.

Note: We are working on an update with MongoDB 3.0 compatibility for the upcoming Robomongo 0.9.x release series.”

via Robomongo — shell-centric MongoDB management tool (MongoDB Admin UI).

Your first app: node.js by Jim Schubert

I started reading the book “Your first app: node.js” by Jim Schubert.

It has a good amount of pages which I really like and teaches us how to create a whole application from installing Node.JS, using npm and adding modules, configure and use the server and client testing tools, building the client side, getting used with MongoDB, using JavaScript the clever way, improving our code on every chapter, to the very end when we will enjoy our completely finished app!

The software tools/libs we will get used to at the and are: Node.js, AngularJS, Express, MongoDB, Git, Bootstrap and more.
The book also has links to a priceless information connected to these tools and JavaScript.

I am at 1/3 of the book and already have learnt things about JavaScript that I would never find easily by myself.

Before that book I’ve started reading 2-3 other books but after some reading and waiting to get the knowledge of creating my own app I couldn’t do anything because I was like reading to random pieces of the documentation. Not that reading the documentation for a new language or framework is not necessary but it should be done after we have some knowledge about how to create an app with it(simple demos, examples) and then using the documentation to upgrade our skills and then write the app in an even better way.

On the book’s page you will find the “table of contents” and a free sample. The price is best too. Do not hesitate and check it now!

MEAN.IO – MongoDB, Express, Angularjs Node.js powered fullstack web framework

My next experiment will be with: MEAN.IO – MongoDB, Express, Angularjs Node.js powered fullstack web framework.

And of course my next book will be: MEAN Machine from Chris Sevilleja and Holly Lloyd on Leanpub.