Redis缓存用户报Unexpected token o in JSON at position 1错误
报错原因
这个报错的核心触发逻辑是:JSON.parse()接收到的入参不是合法的JSON格式字符串,当传入值是JS对象(含Promise对象、普通Object)时,JS会先隐式调用入参的toString()方法转成字符串,这类对象转字符串的结果固定为"[object Xxx]",字符串索引0位置是[、索引1位置是o,和报错信息里position 1位置出现非法字符o完全吻合。
对应到你的代码,有3个明确问题:
- 调用
client.get()读取Redis缓存时没有加await关键字。Node.js生态的Redis客户端所有IO操作都是异步的,不加await拿到的不是缓存的字符串值,而是一个未完成的Promise对象,把这个对象传入JSON.parse()就会触发你看到的报错。 - 缓存写入逻辑后多了一行无意义的
throw error;,这里的error变量从未被定义,代码走到这行必然抛出未定义变量错误,且该行后面的console.log(error)永远不会执行。 - 缓存key硬编码为
name,和请求的用户id完全无关,会导致所有用户查询请求都读写同一个缓存值,出现数据串号问题。 - 数据库查询到用户数据后没有正常返回响应,逻辑被无效的throw打断,前端拿不到正确的查询结果。
修复方案
按以下步骤修改代码即可:
- 给
client.get()、client.set()调用都加上await关键字,确保拿到实际的Redis操作返回值 - 删除多余的
throw error;无效代码 - 将缓存key改为和用户id绑定的格式(如
user:${id}),避免不同用户缓存互相覆盖 - 补上数据库查询成功后的响应返回逻辑,修正缓存成功提示的拼写错误
修复后的完整代码如下:
exports.getOne = async (req, res) => { let id = req.params.id; try { // 加await读取缓存,key绑定用户id做隔离 const cachedUser = await client.get(`user:${id}`); if(cachedUser){ const userData = JSON.parse(cachedUser); console.log(userData); return res.status(200).send(userData); } let user = await User.findById(id); if(!user) { return res.status(400).json('This user does not exist'); } // 加await写入缓存 await client.set(`user:${id}`, JSON.stringify(user)); console.log('Successfully cached') // 正常返回查询到的用户数据 return res.status(200).send(user); } catch (error) { console.log(error); return res.status(500).json(error.message) } }
内容的提问来源于stack exchange,提问作者Gregzone
相关产品推荐
相关产品推荐

