Discord.js v12+运行报SyntaxError: Unexpected end of JSON input问题求助
报错核心原因
SyntaxError: Unexpected end of JSON input 本质是你读取到的stickyones.json内容不完整,不符合JSON格式规范,导致JSON.parse解析失败。
触发问题的具体原因
- 你使用异步的
fs.writeFile写入文件,同时在message事件回调里用同步方法读取文件,会出现读写竞态:写操作还没完成,新的消息事件触发就去读取文件,此时JSON文件只写了一半,内容不完整,解析直接报错。 - 额外错误:
JSON.parse是同步方法,前面加await完全无效,属于多余代码。
修复方案
- 移除
JSON.parse前多余的await - 把异步写文件替换为同步写文件
fs.writeFileSync,避免读写竞态,或者加读写锁控制访问顺序 - 给JSON解析逻辑加
try catch捕获异常,解析失败时使用默认值兜底,避免程序直接崩溃 - 优化逻辑:无需每次消息触发都读取磁盘文件,可以把
stickies数据缓存到内存中,修改时同时更新内存和文件,减少磁盘IO,从根源避免反复读文件带来的问题
修复后代码示例
主逻辑代码
// 初始化时读一次文件存在内存即可,不用每次事件都重复读 let stickies = {} // 初始化加错误捕获 try { stickies = JSON.parse(fs.readFileSync("./stickyones.json", "utf8")); } catch (e) { // 解析失败就用空对象兜底,同时写回文件修复损坏的内容 stickies = {} fs.writeFileSync("./stickyones.json", JSON.stringify(stickies)) } bot.on('message', async (message) => { if (message.author.id == bot.user.id) return; if(!message.guild) return if(stickies[message.channel.id]) { try { let lastMessage = await message.channel.messages.fetch(stickies[message.channel.id].lastId); await lastMessage.delete(); let newMessage = await message.channel.send(`:warning: __***Sticky Message, Read Before Typing!***__ :warning:\n${stickies[message.channel.id].message}`); stickies[message.channel.id] = { lastId: newMessage.id, message: stickies[message.channel.id].message }; // 改用同步写文件,保证写完之后才会处理后续逻辑 fs.writeFileSync("stickyones.json", JSON.stringify(stickies)); } catch (err) { console.log(err) } } });
removesticky命令代码
const Discord = require("discord.js"); const fs = require("graceful-fs"); const ms = require("ms"); // 直接用全局缓存的stickies即可,不用重复读;如果没有全局缓存就保留下面的读取逻辑加错误捕获 let stickies = {} try { stickies = JSON.parse(fs.readFileSync("./stickyones.json", "utf8")); } catch (e) { stickies = {} fs.writeFileSync("./stickyones.json", JSON.stringify(stickies)) } module.exports.run = async (bot, message, args) => { message.delete(); if(!message.member.roles.cache.some(r=>["834130492219588671", "858710670299627551"].includes(r.id)) ) { return message.channel.send(`${message.author}, No.`) } if(stickies[message.channel.id]) { delete stickies[message.channel.id]; // 改用同步写文件 fs.writeFileSync("./stickyones.json", JSON.stringify(stickies)); return message.channel.send("Sticky message removed.").then(msg => { msg.delete({ timeout: 10000 }) }) .catch(console.error); } else { return message.channel.send("There's no sticky set in this channel.").then(msg => { msg.delete({ timeout: 10000 }) }) .catch(console.error); } } module.exports.help = { name: "removesticky" }
内容的提问来源于stack exchange,提问作者cylence
相关产品推荐
相关产品推荐

