48

Can someone give me an example on how to use a Promise with mongoose. Here is what I have, but its not working as expected:

app.use(function (req, res, next) {
  res.local('myStuff', myLib.process(req.path, something));
  console.log(res.local('myStuff'));
  next();
});

and then in myLib, I would have something like this:

exports.process = function ( r, callback ) {
  var promise = new mongoose.Promise;
  if(callback) promise.addBack(callback);

  Content.find( {route : r }, function (err, docs) {
     promise.resolve.bind(promise)(err, docs);

  });

  return promise;

};

At some point I am expecting my data to be present, but how can I access it, or get at it?

royhowie
  • 11,075
  • 14
  • 50
  • 67
user600314
  • 662
  • 1
  • 5
  • 17

6 Answers6

48

In the current version of Mongoose, the exec() method returns a Promise, so you can do the following:

exports.process = function(r) {
    return Content.find({route: r}).exec();
}

Then, when you would like to get the data, you should make it async:

app.use(function(req, res, next) {
     res.local('myStuff', myLib.process(req.path));
     res.local('myStuff')
         .then(function(doc) {  // <- this is the Promise interface.
             console.log(doc);
             next();
         }, function(err) {
             // handle error here.
         });
});

For more information about promises, there's a wonderful article that I recently read: http://spion.github.io/posts/why-i-am-switching-to-promises.html

Adam Zerner
  • 17,797
  • 15
  • 90
  • 156
Alexander Shtuchkin
  • 1,797
  • 15
  • 20
  • 12
    The newest version of mongoose also lets you use the result of `find()` as a promise, without needing to call `exec`. So you could just do: `Content.find({route: r}).then(function(content) { } );` – Jamie Jul 10 '15 at 18:38
  • why do you use res.local? can you directly use `var a = myLib.process(req.path)` – OMGPOP Jul 15 '15 at 07:40
  • @OMGPOP I think OP wanted to use promise in templates. Yes, you can use it directly. – Alexander Shtuchkin Jul 16 '15 at 08:24
30

Mongoose already uses promises, when you call exec() on a query.

var promise = Content.find( {route : r }).exec();
konsumer
  • 3,411
  • 1
  • 30
  • 31
23

Mongoose 4.0 Release Notes

Mongoose 4.0 brings some exciting new functionality: schema validation in the browser, query middleware, validation on update, and promises for async operations.

With mongoose@4.1 you can use any promises that you want

var mongoose = require('mongoose');
mongoose.Promise = require('bluebird');

Another example with polyfilling global.Promise

require('es6-promise').polyfill();
var mongoose = require('mongoose');

So, you can just do later

Content
  .find({route : r})
  .then(function(docs) {}, function(err) {});

Or

Content
  .find({route : r})
  .then(function(docs) {})
  .catch(function(err) {});

P.S. Mongoose 5.0

Mongoose 5.0 will use native promises by default if available, otherwise no promises. You will still be able to set a custom promises library using mongoose.Promise = require('bluebird');, however, mpromise will not be supported.

Alexey B.
  • 11,965
  • 2
  • 49
  • 73
5

I believe you're looking for

exports.process = function ( r, callback ) {
  var promise = new mongoose.Promise;
  if(callback) promise.addBack(callback);

  Content.find( {route : r }, function (err, docs) {
     if(err) {
       promise.error(err);
       return;
     }
     promise.complete(docs);

  });

  return promise;

};
royhowie
  • 11,075
  • 14
  • 50
  • 67
deedubs
  • 282
  • 1
  • 6
0

On this page:http://mongoosejs.com/docs/promises.html

The title is Plugging in your own Promises Library

Mr.Thanks
  • 215
  • 3
  • 7
-1

Use the bluebird Promise library like this:

var Promise = require('bluebird');
var mongoose = require('mongoose');
var mongoose = Promise.promisifyAll(mongoose);

User.findAsync({}).then(function(users){
  console.log(users)
})

This is thenable, such as:

User.findAsync({}).then(function(users){
      console.log(users)
    }).then(function(){
      // more async stuff
    })
Anthony
  • 13,434
  • 14
  • 60
  • 80