解决mongoose中addTask方法报concat未定义的TypeError
解决Mongoose实例方法中this.tasks undefined的问题
用户通过Mongoose定义包含tasks数组的userSchema,尝试用实例方法addTask向tasks添加数据时,报错TypeError: Cannot read properties of undefined (reading 'concat'),相关代码如下:
userSchema代码
const mongoose = require("mongoose"); const userSchema = new mongoose.Schema({ name:{ type: String, required: true }, email:{ type: String, required: true }, password:{ type: String, required: true }, tasks:[ { title: { type: String, }, description: { type: String, }, date: { type: Date, default: Date.now }, author: { type: String, }, isDone: { type: Boolean }, isFail: { type: Boolean } }] }) // creating task userSchema.methods.addTask = async(title, description, author)=>{ try { this.tasks = this.tasks.concat({title, description, author}); await this.save(); return this.tasks; } catch (error) { console.log(error); } } const User = mongoose.model("User", userSchema); module.exports = User;
POST方法代码
router.post("/createtask", async(req, res)=>{ try { const {title, description, author} = req.body; console.log("creating a new task"); if(!title){ return res.json({error: "plz fill title"}); } const userfound = await User.findOne({email: req.body.email}); console.log(userfound); if(userfound){ const userTask = await userfound.addTask(title, description, author); await userfound.save(); res.status(201).json({message: "successfully created a task."}); } } catch (error) { console.log(error); } })
错误原因
- 箭头函数导致this指向错误:实例方法使用箭头函数时,
this不会绑定到Mongoose的User文档实例,而是继承外层作用域的上下文,因此this.tasks为undefined,调用concat时触发报错。 - 重复执行save操作:POST方法中调用
userfound.addTask后又执行userfound.save(),但addTask内部已经完成了保存,属于冗余操作。
解决方案
1. 修改实例方法为普通函数
将addTask的箭头函数改为普通函数,让this正确绑定到当前文档实例,同时增加数组初始化判断:
userSchema.methods.addTask = async function(title, description, author) { try { // 确保tasks数组存在,避免未初始化的情况 this.tasks = this.tasks || []; this.tasks = this.tasks.concat({title, description, author}); await this.save(); return this.tasks; } catch (error) { console.log(error); } }
2. 优化POST方法,移除重复save
router.post("/createtask", async(req, res)=>{ try { const {title, description, author, email} = req.body; console.log("creating a new task"); if(!title){ return res.json({error: "plz fill title"}); } const userfound = await User.findOne({email}); console.log(userfound); if(userfound){ await userfound.addTask(title, description, author); res.status(201).json({message: "successfully created a task."}); } else { res.status(404).json({error: "User not found"}); } } catch (error) { console.log(error); res.status(500).json({error: "Server error"}); } })
3. 可选:Schema层面设置tasks默认空数组
从根源避免tasks为undefined的情况:
tasks: { type: [{ title: { type: String }, description: { type: String }, date: { type: Date, default: Date.now }, author: { type: String }, isDone: { type: Boolean }, isFail: { type: Boolean } }], default: [] }
内容的提问来源于stack exchange,提问作者Jatin
相关产品推荐
相关产品推荐

