Ned
Ned

Reputation: 4141

Using Waterline find method with promisses

I'm stuck when it comes to returning response, from method that includes database call.

Here's sample of what I need...

service.js

 module.exports = {
    getUserStatus: function(userId){
      return User
             .find()
             .where({userId: userId)
             .exec(function(err, user){
               return user.status;
             }
    }
 }

In this service.js, I should fetch user's status and if I console.log(user.status) inside exec method, that is printed OK (I got status).

The problem is I need this result outside service.js:

controller.js

// this code is extracted from longer file, just for demo purpose.
// userService is required 'service.js'
index: function(req, res) {
   var status = userService.getUserStatus(req.session.User.id);
   console.log(status);
   return res.view({userStatus: status});
}

If I console.log(status) here, it will be undefined. I guess that it has something to do with promises and stuff (because of the async calls), but not sure what is the right way to do it.

Upvotes: 0

Views: 150

Answers (1)

sgress454
sgress454

Reputation: 24948

getUserStatus contains asynchronous code, so it needs a callback:

 module.exports = {
    getUserStatus: function(userId, cb){
      User.findOne().where({userId: userId}).exec(function(err, user){
          if (err) return cb(err);
          return cb(null, user.status);
      });
    }
 }

then in the code that uses it:

index: function(req, res) {
   userService.getUserStatus(req.session.User.id, function(err, status) {
       // If an error was returned from the service, bail out
       if (err) {return res.serverError(err);}
       console.log(status);
       return res.view({userStatus: status});
   });
}

Note the use of findOne instead of find; find will return an array.

An alternative would be to return a promise from the service function, and chain your controller code with .then() and .fail():

 module.exports = {
    getUserStatus: function(userId, cb){
      return User.findOne().where({userId: userId});
    }
 }

index: function(req, res) {
   userService.getUserStatus(req.session.User.id)
       .then(function(user) {
           console.log(user.status);
           return res.view({userStatus: user.status});
       })
       .fail(function(err) {
           return res.serverError(err);
       });
   });
}

It's a matter of preference, but I think the first method is better especially in your case, since it allows the service call to deliver just the status, rather than the whole user object. In general, getting used to the standard (err, result) callback method in Node will serve you well.

Upvotes: 2

Related Questions