Combining mongoose and Q in node.js

This post will teach you how to write promise-based mongoose code, using Kris Kowal’s Q library.

You can also find the code below in the src/mongoose-and-q dir of my blog code repository.

We have a mongo database with 3 collections: users, bicycles and cars. Bicycles and cars are owned by users. We will write a script that shows the bicycles and cars owned by  rupert@example.com .

We’ll look at multiple versions of this script. This article focuses on callbacks and promises, so we’ll be using a hardcoded email address and we’ll not be handling errors very well. Those aspects of the code are for a different article.

The first version uses callbacks for the database calls.

Two things stand out in this code. First, the indenting in getVehicles . It looks bad. It is bad. And if we want to add more callbacks, it gets worse. Second, we are using error handling code in each individual callback.

We can rewrite this code to use Q .

The getVehicles  function now returns the promise created on line 33. The user is found, then the cars, then the bicycles, and then the promise resolves to the same object as in the first listing.

This version of  getVehicles looks better regarding both indenting and error handling. The indenting stays on the same level, and the error handling – no matter where the error happens – is done by the catch  block after calling getVehicles .

However, there is also a disadvantage to this code. The vars from a then  block can’t be used in the next then  block, because each consecutive then  block has its own function scope. That’s why we have to assign user  and cars  to helper vars outside their scope.

We can do better. Let’s look at our improved version of getVehicles .

We use Q.all(arrayOfPromises) to retrieve both the cars  and the bicycles  in one go. Q.all  resolves to a list of fulfilment values, which end up in an array in the then  block.

This both makes the code shorter and gets rid of the helper variables. There is one minor improvement that we can still make.

We replace .then  by .spread , so the bicycles  and cars  end up in one argument each, instead of an array of results. Additionally, because .spread  calls .all  initially, we can now remove Q.all and return just the array of promises. This code is more readable and maintainable than the previous version.

This entry was posted in JavaScript, node.js, software development and tagged , , , , , , , , , . Bookmark the permalink.

4 Responses to Combining mongoose and Q in node.js

  1. Chris says:

    Brilliant

  2. Say says:

    This is a great post! I understand promises with these chockful examples. I do have a question on error handling though. How would i manage err returning from each find?

    • Joost says:

      You have a few options. The easiest one is probably to add a catch to wherever you call getVehicles:


      getVehicles('test@example.com')
      .then(function(result) {
      // do something
      })
      .catch(function(err) {
      console.error(err);
      // possibly recover from error
      });

      The way getVehicles has been coded, it returns a promise, and this promise will be rejected if any of the find operations fails.

      You could also add .catch() to each individual find, but the code probably doesn’t know what to do if an error happens there. The calling function might know what to do.

  3. David Basilio says:

    How do you use Q with function save of mongoose ?

Leave a Reply

Your email address will not be published.