1、场景
1、当用户主动退出登录
2、当用户关闭当前页面
3、当用户的session信息过期时
2、思路
1、前两个场景可以编写接口,前端在合适时机调用
router.post('/logout', async (req, res, next) => { await userModel.updateOne({ _id: req.session.userId }, { online: 0 }) // 1:关闭窗口 2:退出登录 if (req.body.type == 1) { res.json({ code: 0, msg: '操作成功' }) } else if (req.body.type === 2) { req.session.destroy(() => { res.json({ code: 0, msg: '操作成功' }) }) } })
2、第三个场景有多种思路
1、编写接口,检查用户的登录状态
router.post('/checkLogin', async (req, res, next) => { if (!req.session.userId) { res.json({ code: 401, msg: '用户未登录' }) return } await userModel.updateOne({ _id: req.session.userId }, { online: 1 }) res.json({ code: 0, msg: '处于登录状态' }) })
2、编写中间件。当用户请求时,检查登录状态
const sessionMiddleWare = async (req, res, next) => { if (!req.session.userId) { res.json({ code: 401, msg: '用户未登录' }) return } next() }
3、登录后,记录登录时间。定时遍历所有用户信息。当某个用户的登录时间+session有效时间等于当前时间的时候。更新用户登录状态
const userModel = require('../db/model/user') const { SESSIONTIME } = require('../config/index') let timer = null const updateUsersOnlineStatus = async () => { try { const start = Date.now() const userData = await userModel.find({ online: 1, loginTime: { $lte: Date.now() - SESSIONTIME } }) if (userData.length > 0) { const bulkOps = userData.map(user => ({ updateOne: { filter: { _id: user._id }, update: { online: 0 }, }, })) await userModel.bulkWrite(bulkOps) } const end = Date.now() const elapsed = end - start const nextInterval = Math.max(0, 1000 * 60 - elapsed) // Ensure next interval is at least 1 minute return nextInterval } catch (error) { console.error('Error updating user online status:', error) return 1000 * 60 // Retry after 1 minute on error } } const startOnlineStatusCheck = async () => { try { const interval = await updateUsersOnlineStatus() if (timer) { clearInterval(timer) } timer = setInterval(updateUsersOnlineStatus, interval) } catch (error) { console.error('Error starting online status check:', error) } } module.exports = startOnlineStatusCheck