node.js:在express保存请求数据时,Cannot read property ‘_id‘ of undefined

大家好,我是梅巴哥er,本篇介绍关于Cannot read property '_id' of undefined这个报错的解决。

俗话说,一杯茶,一支烟,一个BUG改一天。

必须要写个博客纪念下,昨天搞到凌晨五点,终于解决了这个问题。主要还是懂的太少,写的项目不多,遇到问题,只能一步步查原因,一点点的搜索,过程非常非常慢,非常非常的艰难。而且这个报错都搜不到解决办法,只能自己摸索。

看前提示:这里面注释掉的代码,都是我在测试时用来验证错误出在哪里的代码。为方便大家理解这个解决问题的思路,注释代码我就保留了。

先看下报错原因:
我分别在cookie和响应数据data中,用到了user._id,本来想着这样用,也没什么错,毕竟保存user的时候,会自动生成一个_id,看似很合理,但是为啥又报错了呢?
(附代码)

// 注册的路由
router.post('/register', function(req, res) {
  
  // 读取请求参数数据
  
  const { username, password, type } = req.body
  // console.log(id)
  // const _id = id
  // console.log(typeof(_id))
  // console.log(req.body)
  // console.log(req.body.username)
  // console.log({ username })
  // console.log(username)
  // console.log({ username, password, type })
  // 处理
  // 1,判断 看用户是否存在
  
  UserModel.findOne( { username }, function(err, user) {
    // console.log(user)
    // console.log(username)
    // console.log(user.username)
    if (user) { // user已存在,user值为true
      // 返回提示错误信息
      res.send({ code: 1, msg: '此用户已存在' })
      // console.log(user)
    } else { // user不存在
      // console.log(user)
      // 保存注册的用户数据
      new UserModel({ username, password: md5(password), type }).save(function(err, user) {
        // console.log(user)
        // 在发送响应数据之前,生成一个cookie(userid: user._id),
        // 并交给浏览器保存
        // 参数maxAge单位是毫秒,表示cookie存活的时间。
        // 1000*60*60*24 是一天
        res.cookie('userid',  user._id , { maxAge: 1000*60*60*24 })

        // 响应数据中,不要携带密码
        const data = { _id: user._id , username, type } 
        res.send({ code: 0, data })
        // console.log(err, user)
        // res.send(user)
      })
    }
  })
  

  // 返回响应数据
})

问题解决:
经多次验证和查找资料,确实出在这个_id的应用上。下面逐条说明错误原因和解决思路。

  • 在往数据库中保存数据时,_id确实会自动生成,但是他是ObjectId类型的数据
  • 做响应时,我们会从后台拿到一个id,这个id是json类型的数据。
  • _idid根本不是同一个类型的,当我们把id拿给_id用的时候,就会报错
  • 思路:我们把从后台拿到的json类型的id转换成ObjectId类型的数据不就可以了吗?
  • 于是:
    • 先做个引入:const ObjectId = require('mongodb').ObjectId
    • 再把从后台拿到的id做个转换: const id = ObjectId(req.body.id)
    • 这时候的id就可以给_id用了。俩数据的类型一致了。即{ _id: id}

附正确完整代码:

var express = require('express');
var router = express.Router();
// UserModel在models.js文件里已经暴露出来了,要拿到这里用,所以要先引入
const UserModel = require('../db/models').UserModel
// console.log(UserModel)
// 引入密码加密的包
const md5 = require('blueimp-md5')

// 如果没有这里的引入,还有后面id的定义,会报错:
// TypeError: Cannot read property '_id' of undefined
// 解决办法就是,先引入,再定义id,最后把user._id换成id即可。

const ObjectId = require('mongodb').ObjectId


/* GET home page. */
router.get('/', function(req, res, next) {
  res.render('index', { title: 'Express' });
});

// 测试: 定义一个路由,实现用户注册
/*
a) path为 /register
b) 请求方式为post
c) 接收username和password参数
d) admin是已注册用户
e) 注册成功,返回: { code:0, data: { _id: 'abc', username: 'xxx', password: '123' } }
f) 注册失败,返回: {code: 1, msg: '此用户已存在'}
*/ 
// router.post('/register', (req, res) => {
//   /* 1,获取请求参数
//      2,处理
//      3,返回响应数据 */
//   const {username, password} = req.body
//   if (username === 'admin') {
//     res.send({code: 1, msg: '此用户已存在'})
//   } else {
//     res.send({ code: 0, data: { id: 'abc', username, password } })
//   }
// })

// 注册的路由
router.post('/register', function(req, res) {
  
  // 读取请求参数数据
  // 此时的id才是后台传过来的id,才能与数据库对照
  const id = ObjectId(req.body.id)
  const { username, password, type } = req.body
  // console.log(id)
  // const _id = id
  // console.log(typeof(_id))
  // console.log(req.body)
  // console.log(req.body.username)
  // console.log({ username })
  // console.log(username)
  // console.log({ username, password, type })
  // 处理
  // 1,判断 看用户是否存在
  
  UserModel.findOne( { username }, function(err, user) {
    // console.log(user)
    // console.log(username)
    // console.log(user.username)
    if (user) { // user已存在,user值为true
      // 返回提示错误信息
      res.send({ code: 1, msg: '此用户已存在' })
      // console.log(user)
    } else { // user不存在
      // console.log(user)
      // 保存注册的用户数据
      new UserModel({ username, password: md5(password), type }).save(function(err, user) {
        // console.log(user)
        // 在发送响应数据之前,生成一个cookie(userid: user._id),
        // 并交给浏览器保存
        // 参数maxAge单位是毫秒,表示cookie存活的时间。
        // 1000*60*60*24 是一天
        res.cookie('userid', id/* user._id */, { maxAge: 1000*60*60*24 })

        // 响应数据中,不要携带密码
        const data = { _id: id/* user._id */, username, type } 
        res.send({ code: 0, data })
        // console.log(err, user)
        // res.send(user)
      })
    }
  })
  

  // 返回响应数据
})

// const userModel = new UserModel({
//     username: 'ming',
//     password: 233,
//     type: 'dashen'
//   })
//   userModel.save((err, user) => {
//     console.log(err, 'user is', user)
//   })

// 登录的路由

module.exports = router;

成功解决,保存测试数据附图如下:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值