简体   繁体   中英

Node Promise - TypeError cannot read property .then of undefined

The two pieces of code below throw a type error:

TypeError: Cannot read property 'then' of undefined.

I feel like I'm missing something fundamental. Remarkable is that the log of 'result' in the second piece of code is done after the error is thrown. Which leads me to believe I might be doing something wrong involving asynch. However I cannot get my head around it, even after reading the suggested questions.

Any help would be greatly appreciated!

router.route('/user/:id')

    .put(auth.authRest, function(req, res) {
      userManager.updateUser(req.params.id, req.body)
        .then(function(response) { // line where error is thrown
          res.send({data:response});
        });
    });

and from userManager:

this.updateUser = function(id, data) {
    User.findOne({ _id: id }).exec(function(err, user){
      if(err) {
        console.log(err);
      } else {
        for(let prop in data) {
          user[prop] = data[prop];
        }

        var result = user.save().catch(function(err){
          console.log(err);
        });

        console.log(result); // this log is done below the error, it does contain a promise
        return result;
      } 
    }).catch(function(err){
      console.log(err);
    });

  };

If you want to use Promises you need to return a Promise from this.updateUser , the return result belongs to the callback you pass to exec and not to the function you assigned to this.updateUser .

this.updateUser = function(id, data) {
  return User.findOne({
    _id: id
  }).exec().then(function(user) {
    for (let prop in data) {
      user[prop] = data[prop];
    }

    var result = user.save().catch(function(err) {
      console.log(err);
    });

    console.log(result); // this log is done below the error, it does contain a promise
    return result;
  }).catch(function(err) {
    console.log(err);
  });

};

Depending on how you want to do the error handling you could shrink it down to:

this.updateUser = function(id, data) {
  return User.findOne({
    _id: id
  }).exec().then(function(user) {
    for (let prop in data) {
      user[prop] = data[prop];
    }

    return user.save();
  }).catch(function(err) {
    console.log(err);
  });
};

'updateUser' method should return a promise, so that .then call in the first method would work.

Try something like below ( used node package 'q')

this.updateUser = function(id, data) {
    var deferred = Q.defer()
    User.findOne({ _id: id }).exec(function(err, user){
      if(err) {
        console.log(err);
        deferred.reject(err)
      } else {
        for(let prop in data) {
          user[prop] = data[prop];
        }

        var result = user.save().catch(function(err){
          console.log(err);
        });

        console.log(result); // this log is done below the error, it does contain a promise
        deferred.resolve(resolve)
        //return result;
      } 
    }).catch(function(err){
        deferred.reject(err)
      console.log(err);
    });

    return deferred.promise

  };

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM