Nodejs Promise TypeError:无法读取属性'然后'未定义的

时间:2017-12-20 10:13:45

标签: node.js express mongoose promise

当我尝试在controller中访问route的功能时出错。我用了mongoose,快递。

错误:

  

TypeError:无法读取属性'然后'未定义的       at /private/var/www/html/sms/server/routes/user.routes.js:70:9       在Layer.handle [as handle_request](/private/var/www/html/sms/node_modules/express/lib/router/layer.js:95:5)       在下一个(/private/var/www/html/sms/node_modules/express/lib/router/route.js:137:13)       在Route.dispatch(/private/var/www/html/sms/node_modules/express/lib/router/route.js:112:3)       在Layer.handle [as handle_request](/private/var/www/html/sms/node_modules/express/lib/router/layer.js:95:5)       at /private/var/www/html/sms/node_modules/express/lib/router/index.js:281:22       在Function.process_params(/private/var/www/html/sms/node_modules/express/lib/router/index.js:335:12)       在下一个(/private/var/www/html/sms/node_modules/express/lib/router/index.js:275:10)       在Function.handle(/private/var/www/html/sms/node_modules/express/lib/router/index.js:174:3)       在路由器(/private/var/www/html/sms/node_modules/express/lib/router/index.js:47:12)       在Layer.handle [as handle_request](/private/var/www/html/sms/node_modules/express/lib/router/layer.js:95:5)       在trim_prefix(/private/var/www/html/sms/node_modules/express/lib/router/index.js:317:13)       at /private/var/www/html/sms/node_modules/express/lib/router/index.js:284:7       在Function.process_params(/private/var/www/html/sms/node_modules/express/lib/router/index.js:335:12)       在下一个(/private/var/www/html/sms/node_modules/express/lib/router/index.js:275:10)       at /private/var/www/html/sms/server.js:65:3 POST / api / user / create 500 27.274 ms - 16(node:11300)UnhandledPromiseRejectionWarning:   未处理的承诺拒绝(拒绝ID:1):错误:此电子邮件是   已经存在。请输入其他电子邮件。 (节点:11300)[DEP0018]   弃用警告:已弃用未处理的承诺拒绝。在   未来,未经处理的承诺拒绝将终止   Node.js使用非零退出代码进行处理。

这是我的代码: -

user.cont.js

function create(data) {
  User.findOne({ email: data.email })
    .exec((err, doc) => {
      if (err) {
        return new Promise((resolve, reject) => {
          return reject(err);
        })
      } else {
        if (doc) {
          return new Promise((resolve, reject) => {
            return reject(new Error('This email is already exists. Please enter another email.'));
          })
        } else {
          const user = new User(data);
          return user.save()
        }
      }

    })

}


export default { getUsers, create };

user.route.js

router.post('/create', (req, res, next) => {
        UserCtrl.create(req.body)
            .then(savedUser => res.json(savedUser)) . // here error is generated
            .catch(e => next(e));
    });

2 个答案:

答案 0 :(得分:0)

您应该将整个User.findOne()调用包装在Promise中,如下所示:

function create(data) {
  return new Promise((resolve, reject) => {
    User.findOne({ email: data.email })
      .exec((err, doc) => {
        if (err) return reject(err)
        if (doc) return reject(new Error('This email is already exists. Please enter another email.'))
        const user = new User(data)
        user.save((err) => {
          if (err) return reject(err)
          resolve()
        })
      })
  })
}

您还需要解析承诺,否则永远不会调用UserCtrl.then()来电中的回调。我还添加了错误处理,以防将新的User保存到数据库时出现问题。

答案 1 :(得分:0)

您也可以像这样重构您的控制器和路由代码。

user.cont.js

function create(req, res, next){
   User.findOne({email: req.body.email})
    .then((err, user) => {

      if(user){

        const newUser = User.create(req.body,  (newUser, err) => {
          if(err) res.send(err);

          delete newUser.password;
          res.json(newUser)
        })
      }


    }).catch((err) => {
       res.send(err)
    })


}

由于User.findOne已经返回了一个承诺,您可以在其上调用.then,因此,出于安全原因,在将用户密码返回给客户端之前,请确保删除用户的密码(如果有)!

请注意,您也可以在create函数上调用.then,也许您可​​以将其重构为使用.then进行练习:)


user.route.js

router.post('/create', UserCtrl.create)

现在,您的路线代码看起来更加整洁,并且您将关注点分离的情况变得更好了!