使用discord.js开发Discord机器人异步与同步代码整合问题求助
问题根因
- 你当前使用的
forEach遍历为同步执行逻辑,不会等待内部异步Promise的then回调执行完成,就直接将未完成赋值的原始finalArgument推入结果数组,最终返回的数组自然都是未处理的原始参数值 - 之前添加
await报错是因为你将await写在了forEach的普通回调函数中,该回调没有被声明为async,不符合await的语法要求
解决方案
第一步:改造参数遍历逻辑
将原来的forEach遍历改为map遍历,为每个参数的处理返回Promise,再通过Promise.all等待所有参数处理完成。你已经将getCommandArgs声明为async函数,直接使用如下代码替换原有遍历逻辑即可:
// 用map生成Promise数组,每个迭代函数声明为async const promiseList = argsList.map(async (argument, index) => { const type = args[index].type if (type === UserArgument) { // 直接await获取异步结果 return await new UserArgument(argument).result } else if (type === MemberArgument) { return await new MemberArgument(argument, guild).result } else if (type === ChannelArgument) { return await new ChannelArgument(argument, guild).result } else if (type === RoleArgument) { return await new RoleArgument(argument, guild).result } // 不需要特殊处理的参数直接返回 return argument }) // 等待所有Promise执行完成,得到最终参数数组 const finalArgList = await Promise.all(promiseList) return finalArgList
Promise.all会在任意一个Promise抛出错误时立即终止执行并抛出该错误,你可以在调用getCommandArgs的外层用try/catch统一捕获参数校验失败的异常,保证错误发生在命令执行之前。
第二步:调整调用侧逻辑
因为getCommandArgs是async函数,返回值为Promise,所以所有调用该函数的位置都需要添加await关键字,或者通过.then回调获取处理后的参数,否则会拿到Promise对象而非实际参数数组。
现有代码隐藏问题修复建议
UserArgument构造函数的Promise逻辑存在无效执行问题:如果传入的是合法数字ID,users.fetch执行后没有终止代码,会继续调用#getUserFromName,虽然Promise状态只会变更一次,但会产生无效请求,建议在if (isNumeric(user))分支的fetch调用前添加return。#getUserFromName方法中遍历用户缓存的写法错误:for...in遍历Map得到的是键,你需要用for (const [userId, user] of ArgumentBase.client.users.cache)才能拿到用户对象,否则当前逻辑永远找不到匹配用户名的用户。
内容的提问来源于stack exchange,提问作者Batimius
相关产品推荐
相关产品推荐

