Question

I'm trying to using the Mongoose Promises to have a cleaner code (see nested functions). Specifically, I'm trying to build something like this:

Model.findOne({_id: req.params.id, client: req.credentials.clientId}).exec()
   .then(function(resource){
      if (!resource) {
        throw new restify.ResourceNotFoundError();
      }
      return resource;
    })
    .then(function(resource) {
      resource.name = req.body.name;
      return resource.save; <-- not correct!
    })
    .then(null, function(err) {
       //handle errors here
    });

So, in one of the promises I would need to save my model. As of the latest stable release, Model.save() does not return a promise (bug is here).

To use the classical save method, I could use this:

   //..before as above
   .then(function(resource) {
      resource.name = req.body.name;
      resource.save(function(err) {
        if (err)
            throw new Error();
        //how do I return OK to the parent promise?
      });
    })

But as also commented in the code, how do I return to the holding promise the return value of the save callback (which runs async)?

Is there a better way?

(btw, findOneAndUpdate is a no-go solution for my case)

Was it helpful?

Solution

One way of doing it would be to wrap the .save code in your own method which returns a promise. You'll need a promise library, like RSVP or Q. I'll write it in RSVP, but you should get the idea.

var save = function(resource) {
  return new RSVP.Promise(function(resolve, reject) {
    resource.save(function(err, resource) {
      if (err) return reject(err);
      resolve(resource);
    });
  });
}

Then in your calling code:

// ...

.then(function(resource) {
  resource.name = req.body.name;
  return save(resource);
})
.then(function(resource) {
  // Whatever
})
.catch(function(err) {
 // handle errors here
});

The other way of doing it would be to nodeify the save method, but I'd do it they way I've detailed above.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top