NodeJS使用Redis存储Refresh Token时报client is closed错误如何解决
问题原因
- 当前使用的
node-redisv4及以上版本API发生了大幅调整:不再默认自动建立Redis连接,所有操作方法均改为Promise异步风格,连接成功事件名也从旧版的connection改为ready - 未手动触发Redis连接初始化,调用
set方法时客户端还处于未连接的关闭状态 - 异步的
set操作未加await处理,也没有异常捕获逻辑,导致抛出未处理的Promise拒绝警告
修复代码
1. 修改redis.js文件
const redis = require('redis'); require('dotenv').config({ path : __dirname + '/../config/env/.env' }); // v4版本createClient传入配置对象,而非分开的端口、地址参数 const redisClient = redis.createClient({ host: '127.0.0.1', port: 6379 // 如果redis设了密码,这里加password字段填密码 }); // 监听连接成功事件 redisClient.on('ready', () => { console.info('Redis connected!'); }); // 监听连接错误 redisClient.on('error', err => { console.error('Redis connect error:', err); }); // 手动触发连接 (async () => { await redisClient.connect(); })(); module.exports = redisClient;
2. 修改authRoute.js接口逻辑
'use strict'; const JwtUtil = require('../../middlewares/jwt-util'); const redisClient = require('../../middlewares/redis'); const authRouter = require('express').Router(); const jwt = new JwtUtil(); // 回调改为async异步函数 authRouter.post('/user-token/generate', async (req, res, next) => { try { const accessToken = jwt.sign(req.body); const refreshToken = jwt.refresh(); // 异步操作加await,同时设置过期时间,和refresh token本身的有效期保持一致 // 示例为7天有效期,可根据自身业务调整 await redisClient.set(req.body.id, refreshToken, { EX: 7 * 24 * 60 * 60 }); res.status(200).send({ result : 'success', data : { accessToken, refreshToken } }); } catch (err) { // 捕获异常返回错误响应 console.error('Generate token error:', err); res.status(500).send({ result: 'fail', msg: '服务内部错误' }); } }); module.exports = authRouter;
额外优化建议
- 后续所有Redis查询、删除、修改操作,都需要加
await处理异步逻辑 - 生产环境建议将Redis的地址、端口、密码、库序号等配置都放到环境变量中读取,不要硬编码在代码里
内容的提问来源于stack exchange,提问作者Minwoo Kim
相关产品推荐
相关产品推荐

