Node.js调用User实例save()方法报错:TypeError: user.save is not a function
问题原因与解决方案
嘿,我完全懂你这个困扰——作为Node.js新手,这种面向对象和数据库交互的小细节确实容易漏掉!
为什么会报错 TypeError: user.save is not a function?
当你通过MongoDB的find()/findOne()方法查询数据时,返回的是普通的JavaScript对象(也就是数据库里的原始文档),并不是你定义的User类的实例。而save()是挂在User.prototype上的方法,只有User类的实例才能调用它,普通对象当然没有这个方法啦!
解决步骤
1. 将查询到的数据库文档转换为User实例
修改你的findByEm方法,拿到数据库返回的文档后,手动创建一个User实例,并把文档的属性全部赋值给这个实例:
static findByEm(em) { const db = getDb(); return db.collection('users') .find({ 'email': em }) .next() .then(userDoc => { if (!userDoc) { console.log('No user found with this email'); return null; } // 创建User实例,复制文档的所有属性 const user = new User(userDoc.email, userDoc.password); // 把MongoDB自动生成的_id及其他属性同步到实例 Object.assign(user, userDoc); console.log('user find test: ', user); return user; }).catch(err => { console.log('error: ', err); }); }
同理,你的findById方法也需要做同样的修改,避免之后调用save()时踩同样的坑:
static findById(userId) { const db = getDb(); return db .collection('users') .findOne({ _id: new ObjectId(userId) }) .then(userDoc => { if (!userDoc) { return null; } const user = new User(userDoc.email, userDoc.password); Object.assign(user, userDoc); console.log(user); return user; }) .catch(err => { console.log(err); }); }
2. 修改save()方法,支持新增和更新操作
原来的save()只做了插入操作,但现在我们需要用它来更新已存在的用户(也就是带_id的实例),所以要调整逻辑:
save() { const db = getDb(); let operation; // 如果实例有_id,说明是已存在的用户,执行更新 if (this._id) { operation = db.collection('users').updateOne( { _id: new ObjectId(this._id) }, { $set: this } // 把实例的所有属性同步到数据库 ); } else { // 没有_id,是新用户,执行插入 operation = db.collection('users').insertOne(this); } return operation .then(result => { console.log('save() result: ', result); return result; }) .catch(err => { console.log('error: ', err); }); }
验证一下
现在当你在postReset里拿到user时,它已经是User类的实例了,调用user.save()就不会再报错,而且能正确更新数据库里的用户记录。
内容的提问来源于stack exchange,提问作者user8758206
相关产品推荐
相关产品推荐

