8

I've started using promises, I use Node.js Mango (with mongoose) and bluebird.. The issue I'm having is for some reason when I chain the mongoose call with functions returning promises (I'm assuming this is the correct way to return and chain) then I get:

typeError: Object #<Promise> has no method 'fail'

if I change the fail to catch then I get the same issue:

typeError: Object #<Promise> has no method 'catch'

what I do is use the function(null, function) pattern which is exactly fail and catch. However the catch / fail is more readable. Any clue why I'm getting this and how I should resolve this issue?

Here is an example of the code block.

User.findOne({ 'email' :  user_email }).exec()
 }).then (promisedTransformUserSchemaToFrontendObjectWithProjectMapping)
   .then (function (feUser) {
       return new Promise(function (resolve, reject) {
          res.json(feUser);
          return resolve(feUser);
      });
   }).fail/catch  (function (err) {
      console.log(err);
      sendError(res,"failed to get user",err);
   });

And here is the stacktrace:

TypeError: Object #<Promise> has no method 'catch'
    at module.exports.app.put.User.update.email (app\controllers\router.js:165:16)
    at callbacks (node_modules\express\lib\router\index.js:164:37)
    at isLoggedIn (app\controllers\router.js:741:10)
    at callbacks (node_modules\express\lib\router\index.js:164:37)
    at param (node_modules\express\lib\router\index.js:138:11)
    at param (node_modules\express\lib\router\index.js:135:11)
    at pass (node_modules\express\lib\router\index.js:145:5)
    at Router._dispatch (node_modules\express\lib\router\index.js:173:5)
    at Object.router (node_modules\express\lib\router\index.js:33:10)
    at next (node_modules\express\node_modules\connect\lib\proto.js:193:15)
Dory Zidon
  • 10,497
  • 2
  • 25
  • 39

4 Answers4

16

mongoose 4.1+ maintainer suggestion:

es2015 (es6):

require('mongoose').Promise = Promise;

bluebird:

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

Q:

require('mongoose').Promise = require('q').Promise;
King Friday
  • 25,132
  • 12
  • 90
  • 84
  • why only +3 ? using require('mongoose').Promise = Promise; easily added support catch and made my world better. Thanks a lot!! – Sulliwane Dec 17 '15 at 15:56
5

I do not know moongose, but in general, functions like fail or catch are convenience shortcuts and are not a part of the promises spec. As such the library does not need to have them to be promises-compliant. Apparently in your case they are not there.

You can achieve same functionality with then(successHandler, rejectionHandler).

In order to handle the promise rejection, you can rewrite your code as follows:

User.findOne({ 'email' :  user_email }).exec()
 }).then (promisedTransformUserSchemaToFrontendObjectWithProjectMapping)
   .then (function (feUser) {
       return new Promise(function (resolve, reject) {
          res.json(feUser);
          return resolve(feUser);
      });
   }).then (undefined, function (err) {
      console.log(err);
      sendError(res,"failed to get user",err);
   });
smyk
  • 346
  • 2
  • 8
3

Another way to do it is shown in the bluebird docs:

https://github.com/petkaantonov/bluebird/blob/master/API.md#promiseresolvedynamic-value---promise

You can wrap the mongoose promise in bluebird's Promise.resolve(), and you will get back a bluebird promise.

 Promise.resolve(User.findOne({ 'email' :  user_email }).exec())
 .then (promisedTransformUserSchemaToFrontendObjectWithProjectMapping)
   .then (function (feUser) {
          res.json(feUser);
          return feUser;
   }).fail/catch  (function (err) {
      console.log(err);
      sendError(res,"failed to get user",err);
   });
Ryan Quinn
  • 1,175
  • 1
  • 15
  • 28
0

It seems that the problem was mixing the two types of promises (bluebird and mongoose)..

Once I used the promsifyAll on the db object, the catch started to work..

// promisify all model using mongoomise..
require('../../mongoomise').promisifyAll(mongoose, require('bluebird'))
Dory Zidon
  • 10,497
  • 2
  • 25
  • 39
  • @MuhammadUmer try this little piece of code I've added, I hope it helps. – Dory Zidon Apr 27 '15 at 17:16
  • If you use mongoose 4.1.0 (released 2015-07-24) or above then you should not use `promisify` with mongoose. Jason Sebring's answer should be preferred (my opinion is that the marked solution should be changed). http://mongoosejs.com/docs/promises.html#plugging-in-your-own-promises-library – ippi Feb 16 '16 at 05:49