Express-session存储用户实例跨路由调用createProduct方法报错咨询
报错根因
你遇到的报错本质是:connect-session-sequelize 存储session数据时会自动将内容序列化为普通JSON对象存入数据库,你直接把Sequelize的User模型实例存入req.session.users时,实例上自带的关联方法(比如你这里用的createProduct是User和Product配置hasMany关联后Sequelize自动生成的实例方法)不会被序列化保存,从session中读取到的req.session.users只是普通的JS对象,自然不存在这个方法。
可行解决方案
方案1:仅在session中存储用户ID,请求时查询实例(最推荐)
这是行业通用的最优做法,避免session存储冗余数据,也能保证拿到的用户数据是最新的。
- 首先修改登录逻辑,仅存储用户ID到session:
const User = require('../models/user') exports.postLoginPage = (req,res,next) =>{ User.findByPk(1) .then(users =>{ req.session.isLoggedIn = true; // 不要存整个实例,仅存用户ID req.session.userId = users.id; res.redirect('/'); }) .catch(err =>{ console.log(err) }) }
- 你提到其他路由可以正常通过
req.user获取数据,说明你的项目已经配置了全局中间件,会自动根据session中的用户信息查询User实例挂载到req上,直接修改商品添加逻辑,使用req.user调用方法即可:
exports.postaddProductsMale = (req,res,next) =>{ const title = req.body.title; const imageUrl = req.body.imageUrl; const price = req.body.price; // 直接用已经挂载好的req.user实例调用方法 req.user.createProduct({ title:title, imageUrl:imageUrl, price:price }) .then(results =>{ console.log('Product created') res.redirect('male_section'); }) .catch(err =>{ console.log(err) }) };
如果你的项目没有配置这个全局中间件,可以自己添加,在所有路由之前挂载:
app.use((req, res, next) => { // 未登录直接放行 if (!req.session.userId) return next(); User.findByPk(req.session.userId) .then(user => { // 将查询到的Sequelize实例挂载到req上 req.user = user; next(); }) .catch(err => console.log(err)) })
方案2:将session中的用户数据还原为Sequelize实例
如果你不想改动现有session存储逻辑,可以在调用方法前手动把session中的普通对象还原为Sequelize实例:
exports.postaddProductsMale = (req,res,next) =>{ const title = req.body.title; const imageUrl = req.body.imageUrl; const price = req.body.price; // 手动还原为User模型实例 const user = User.build(req.session.users); user.createProduct({ title:title, imageUrl:imageUrl, price:price }) // 后续逻辑和原代码保持一致即可 }
该方案不推荐,因为session中存储的用户数据可能和数据库最新数据不一致,容易出现逻辑问题。
内容的提问来源于stack exchange,提问作者Ilamaaran Ramakrishnan
相关产品推荐
相关产品推荐

