Nodejs mongoose model里的session没反应,求救

Nodejs mongoose model里的session没反应,求救

各位大虾,小弟在使用session时出了一些问题

我确认过req.session是有作用的,但是放在mongoose model callback里面的session操作却没有反应,这是为什么??

以下是我的代码

signin: function(req, res){

req.session.test = “test1”; //可以作用

User.findOne({name: req.body.account}, function(err, user){
req.session.test = “test2”; //没有作用 });

res.cookie("blog", {
	account: req.body.account,
	password: req.body.password
}, {path: '/', maxAge: 1000 * 60 * 60 * 24 * 30});

res.render('signin', {
	title: 'signin'
});

}


4 回复

Node.js Mongoose Model 里的 Session 没有反应,求救

各位大虾,小弟在使用 session 时遇到了一些问题。我确认过 req.session 是起作用的,但是在 mongoose model 的回调函数里面对 req.session 的操作却没有反应。这是为什么呢?

问题描述

我的代码如下:

signin: function(req, res) {

  // 这行代码可以正常设置 session
  req.session.test = "test1";

  User.findOne({ name: req.body.account }, function(err, user) {
    if (err) {
      console.error(err);
      return;
    }
    
    // 这行代码没有生效
    req.session.test = "test2";
  });

  // 设置 cookie
  res.cookie("blog", {
    account: req.body.account,
    password: req.body.password
  }, { path: '/', maxAge: 1000 * 60 * 60 * 24 * 30 });

  // 渲染视图
  res.render('signin', {
    title: 'signin'
  });
}

原因分析

User.findOne 回调函数内部,Mongoose 异步查询数据库,而 res.renderres.cookie 是同步执行的。这意味着当 User.findOne 的回调被执行时,响应可能已经发送给客户端了(即 res.end() 已经被调用),这导致 req.session 的更改没有机会被保存到存储中。

解决方案

要解决这个问题,可以在 User.findOne 的回调函数中确保所有的 session 更新都已完成之后再渲染视图或发送响应。一种常见的做法是将这些操作封装在一个异步函数中,并等待所有操作完成后再进行下一步。

以下是改进后的代码:

signin: async function(req, res) {

  // 设置 session
  req.session.test = "test1";

  try {
    const user = await User.findOne({ name: req.body.account }).exec();
    
    // 更新 session
    req.session.test = "test2";

    // 设置 cookie
    res.cookie("blog", {
      account: req.body.account,
      password: req.body.password
    }, { path: '/', maxAge: 1000 * 60 * 60 * 24 * 30 });
    
    // 渲染视图
    res.render('signin', {
      title: 'signin'
    });
  } catch (err) {
    console.error(err);
    res.status(500).send('Internal Server Error');
  }
}

在这个改进后的代码中,我们使用 async/await 来处理异步操作,确保在更新 session 之后再渲染视图和设置 cookie。这样可以保证所有的 session 更新都能成功保存到存储中。


哥哥,在你req.session.test = “test2”;之前你就调用了res.render(‘signin’, { title: ‘signin’ });哈哈,咋起作用啊,你这样试试 <pre><code>

User.findOne({name: req.body.account}, function(err, user){  
    req.session.test = "test2";   
    res.cookie("blog", {
    account: req.body.account,
    password: req.body.password
     }, {path: '/', maxAge: 1000 * 60 * 60 * 24 * 30});

res.render(‘signin’, { title: ‘signin’ }); });

</pre></code>

多谢,终于解决了~

在Node.js中使用Mongoose模型时,如果你在findOne回调函数内部修改了req.session,可能会遇到会话不更新的问题。这是因为Mongoose的查询是异步执行的,而Express的会话中间件(如express-session)默认情况下不会为每次请求重新加载会话数据。

解释

当你在User.findOne的回调函数内部修改req.session时,这个修改实际上是发生在异步回调中。然而,由于会话数据是在请求处理开始时加载到内存中的,并且通常在请求结束时才会被持久化,如果在异步操作完成之前请求已经结束,那么这个修改可能不会被保存。

解决方案

你可以使用touch方法来手动确保会话数据被持久化。或者更简单地,在完成所有异步操作后,通过调用req.session.save()来手动保存会话数据。

示例代码

const express = require('express');
const session = require('express-session');
const mongoose = require('mongoose');

const app = express();
app.use(session({
    secret: 'your-secret-key',
    resave: false,
    saveUninitialized: true
}));

// 假设User模型已经定义好
const User = mongoose.model('User', new mongoose.Schema({ name: String }));

app.post('/signin', async (req, res) => {
    req.session.test = "test1";

    try {
        const user = await User.findOne({ name: req.body.account });
        if (user) {
            req.session.test = "test2";
            req.session.save((err) => {
                if (err) console.error('Failed to save session:', err);
            });
        } else {
            // 处理找不到用户的情况
        }
    } catch (error) {
        console.error('Database error:', error);
    }

    res.cookie("blog", {
        account: req.body.account,
        password: req.body.password
    }, { path: '/', maxAge: 1000 * 60 * 60 * 24 * 30 });

    res.render('signin', {
        title: 'signin'
    });
});

app.listen(3000, () => {
    console.log('Server is running on port 3000');
});

在这个例子中,我们使用了async/await语法来简化异步操作,并确保在修改会话数据后调用req.session.save()方法来保存这些更改。

回到顶部