如何修复discord.js中forEach与await搭配的语法错误
解决discord.js voiceStateUpdate中forEach异步回调与await的语法错误
问题根源
你遇到的SyntaxError有两个核心原因:
fs.readFile的普通回调函数不是async函数,内部无法使用awaitforEach的异步回调无法被正确等待,且本身不支持异步流程控制
以下是两种可行的解决方案,推荐第一种来保证异步流程的可控性:
方案一:使用for...of替代forEach + 改用Promise版fs API
这种方式能精准控制异步执行顺序,避免并发过载,同时消除嵌套回调:
// 确保导入Discord相关模块 const { AttachmentBuilder } = require('discord.js'); const Canvas = require('canvas'); const fs = require('fs').promises; // 直接使用Promise版fs client.on('voiceStateUpdate', async (oldState, newState) => { // 检测用户进入指定语音频道 if (!oldState.channel && newState.channel.id === '你的目标频道ID') { const targetRole = newState.guild.roles.cache.get('你的目标角色ID'); if (!targetRole) return; // 用for...of遍历成员,支持await等待异步操作 for (const member of targetRole.members.values()) { try { // 读取背景图(Promise版,支持await) const imageBuffer = await fs.readFile('背景图文件路径'); // 加载图片到Canvas(await生效,因为当前函数是async) const background = await Canvas.loadImage(imageBuffer); // 生成Canvas图片逻辑示例 const canvas = Canvas.createCanvas(800, 600); const ctx = canvas.getContext('2d'); ctx.drawImage(background, 0, 0, canvas.width, canvas.height); // 可添加其他绘制逻辑(比如用户名、头像等) // 发送图片给成员 const attachment = new AttachmentBuilder(canvas.toBuffer(), { name: 'welcome.png' }); await member.send({ files: [attachment] }); } catch (err) { console.error(`处理成员${member.id}时出错:`, err); } } } });
关键改进点:
- 将
voiceStateUpdate的事件回调标记为async,允许内部使用await - 用
for...of替代forEach,支持逐个等待异步操作完成,避免并发触发过多API请求 - 使用
fs.promises.readFile替代回调版fs.readFile,消除嵌套回调并支持await - 添加
try/catch捕获异步操作中的错误,防止程序崩溃
方案二:保留forEach但修正异步回调(不推荐)
如果一定要用forEach,需将回调设为async,同时把fs.readFile转为Promise式,但要注意forEach不会等待每个回调完成,可能引发并发限制问题:
const { AttachmentBuilder } = require('discord.js'); const Canvas = require('canvas'); const fs = require('fs'); const util = require('util'); const readFile = util.promisify(fs.readFile); // 把回调API转为Promise client.on('voiceStateUpdate', (oldState, newState) => { if (!oldState.channel && newState.channel.id === '你的目标频道ID') { const targetRole = newState.guild.roles.cache.get('你的目标角色ID'); if (!targetRole) return; targetRole.members.forEach(async (member) => { try { const imageBuffer = await readFile('背景图文件路径'); const background = await Canvas.loadImage(imageBuffer); // 生成Canvas图片并发送的逻辑 const canvas = Canvas.createCanvas(800, 600); const ctx = canvas.getContext('2d'); ctx.drawImage(background, 0, 0, canvas.width, canvas.height); const attachment = new AttachmentBuilder(canvas.toBuffer(), { name: 'welcome.png' }); await member.send({ files: [attachment] }); } catch (err) { console.error(err); } }); } });
注意事项:
forEach会同时触发所有异步回调,若目标角色成员数量较多,可能触发Discord的API速率限制- 无法保证异步操作的执行顺序,适合对执行顺序无要求且成员数量较少的场景
内容的提问来源于stack exchange,提问作者El3oso
相关产品推荐
相关产品推荐

