大家好,我是梅巴哥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
类型的数据。 _id
和id
根本不是同一个类型的,当我们把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;
成功解决,保存测试数据附图如下: