0

So I have this method for a User object to check for an existing record.

User.findOrCreate = function(json){
    User.findOne({'email' : json.email}, function(err, user){
        if (!user){
            user = new User({
                id: json.id,
                email: json.email,
                f_name: json.first_name,
                l_name: json.last_name,
                gender: json.gender,
                locale: json.locale
            });
            user.save(function(err){
                if (err) return handleError(err);
                return user;
            });
        } else {
            return user;
        }
    });
}

so basically I want to return the variable "user" to the method findOrCreate, so that I can use it in another place like so:

var user = User.findOrCreate(profile._json);

But instead, user = undefined when I log it out. Having a lot of trouble with this. Can anyone help?

2 Answers2

0

The User.getOrCreate function has not any return statement, so of course it will return undefined, in fact findOne is working async, so your getOrCreate function should be async too, So you can change your function definition to:

User.findOrCreate = function(json, callback) {

and instead of return user; you should run the callback function:

callback(user);
MostafaR
  • 3,547
  • 1
  • 17
  • 24
0

You can't do this:

var user = User.findOrCreate(profile._json);

Because the execution of User.findOne is async, so when findOrCreate returns, probably User.findOne wasn't executed yet.

The right way of getting the user value is to use another callback in findOrCreate:

User.findOrCreate = function(json, callback){
    User.findOne({'email' : json.email}, function(err, user){
       if (!user){
           user = new User({
               id: json.id,
               email: json.email,
               f_name: json.first_name,
               l_name: json.last_name,
               gender: json.gender,
               locale: json.locale
            });
            user.save(function(err){
               if (err) return handleError(err);
               callback(user);
            });
        } else {
            callback(user);
        }
     });
};

As you can see handling all of those callbacks can make you mad. If you didn't tried promises yet take a look to the Q library: http://documentup.com/kriskowal/q/

It will make your life easy:

 var userPromise = User.findOrCreate(profile._json);
 /* then when you need a user */
 userPromise.done(function (user) { /* do something */ });

The advantage is that promises comes with very useful abstractions to handle control flow of async code, for example using promises you can write findOrCreate like this:

  User.findOrCreate = function(json) {
       return User.findOne({email:json.email}).then(createIfNull);
  };

Where createIfNull is the code that you have inside the if block (if save also returns a promise things are easy.. if not you can create one and return it, see Q examples... the docs are not very intuitive but once that you get used to it you'll see that it really simplifies all the callback mess).

Diego
  • 4,353
  • 1
  • 24
  • 22