我从数据库中检索user对象,并将其设置在express-session上:
export const postLogin = async (
request: Request,
response: Response,
next: NextFunction
): Promise<void> => {
try {
request.session.user = await UserModel.findById('6127bd9d204a47128947a07d').orFail().exec()
response.redirect('/')
} catch (error) {
next(error)
}
}然后,我在user对象上调用Mongoose方法populate(),以获取与其关联的购物车:
export const getCart = async (
request: Request,
response: Response,
next: NextFunction
): Promise<void> => {
try {
const userWithCartProducts = await request.session.user
.populate('cart.items.productId')
.execPopulate()
} catch (error) {
next(error)
}
}但是在这里我得到了一个错误:TypeError: request.session.user.populate is not a function
我在express-session上定义了自定义用户类型,如下所示:
declare module 'express-session' {
interface SessionData {
user?: DocumentType<User>
}
}正如您在上面对user的定义中所看到的,我使用DocumentType<User>是因为我使用Typegoose输入模型。我不确定Typegoose是不是这样做的。
我做错了什么?任何意见都将非常感谢。
发布于 2021-10-13 12:47:29
问题是session对象中的user对象是由MongoDBStore获取的。MongoDBStore不知道Typegoose中定义的User模型,因此,当它从会话数据库中获取数据时,它只获取原始数据,而不是在Typegoose模型中定义的方法。
因此,为了解决这个问题,在中间件中,当一个新的请求进入时,在初始化快速会话之后,我们需要从数据库中获取用户一次,并将其放入request对象中,如下所示:
app.use(initializeUser)
export const initializeUser = async (request: Request, response: Response, next: NextFunction): Promise<void> => {
try {
request.user = await User.findById(request.session.user._id).orFail().exec()
next()
} catch (error) {
next(error)
}
}对于Typegoose,在Request上定义User模型,如下所示:
declare global {
declare namespace Express {
export interface Request {
user?: DocumentType<User>
}
}
}正如问题中提到的,在login路由中,即使我们将user对象存储在session中,请求也会终止,并且会话(以及user对象)将保存到数据库中。但是下一次request进入时,session中可用的user对象将被MongoDBStore检索,它不知道User模型和Typegoose定义的方法。所以,这就是我们解决这个问题的方法。同样的解决方案也适用于Mongoose的Javascript。
https://stackoverflow.com/questions/69243249
复制相似问题