如何解决Discord.js中await messages引发的未处理Promise拒绝及TypeError问题
问题分析与解决方案
先帮你拆解下触发错误的核心原因,再给出针对性的修复方案:
1. 核心错误根源
(1)awaitMessages 参数顺序完全错误
Discord.js 里 MessageChannel.awaitMessages() 的第一个参数必须是过滤函数(用来筛选要收集的消息),第二个参数才是配置选项(比如max、time)。你直接把配置对象当成第一个参数传入,导致内部代码试图把这个对象当作函数调用apply,这就触发了TypeError: Function.prototype.apply was called on #<Object>这个致命错误。
(2)循环内异步逻辑混乱
- 用
var x会导致所有异步回调共享同一个变量值,引发迭代逻辑错误; message.author.send()是异步操作,你在它的then回调里才赋值dmCh,但紧接着就调用dmCh.awaitMessages()——这时候dmCh大概率还没被赋值,进一步加剧了错误;- 循环会一次性触发所有消息发送和收集器,多个收集器同时运行不仅逻辑混乱,还会引发未处理的Promise拒绝警告。
2. 修复后的完整代码
我们用async/await理顺异步逻辑,修正参数顺序,同时解决作用域问题:
// 把这段代码放在一个async函数内部(比如你的命令执行函数里) async function startQuestionnaire(message, questions) { try { const answers = []; // 先建立私信频道,确保后续操作都有合法的频道对象 const dmChannel = await message.author.send({ embed: { title: "问卷启动", description: "请诚实回答以下问题,涉及个人信息请提供真实内容,每题有1分钟作答时间", color: 0xe556f5 } }).then(msg => msg.channel) .catch(err => { throw new Error("无法给你发送私信,请检查你的私信设置是否开启"); }); // 逐个处理问题,确保上一个问题完成后再发下一个 for (let x = 0; x < questions.length; x++) { // 发送当前问题 await dmChannel.send({ embed: { title: `***Q${x + 1}. ${questions[x]}***`, footer: { text: "你有1分钟时间回答!" }, color: 0xe556f5 } }); // 等待用户回答:第一个参数是过滤函数,只收集当前用户的消息 const collected = await dmChannel.awaitMessages( msg => msg.author.id === message.author.id, { max: 1, time: 60000, errors: ["time"] } ); // 提取并保存回答 const userAnswer = collected.first().content.toLowerCase(); answers.push(userAnswer); console.log(`收到第${x+1}题回答:${userAnswer}`); } // 问卷完成后的收尾 await dmChannel.send({ embed: { title: "问卷完成!", description: "感谢你的配合与诚实回答", color: 0x43b581 } }); console.log("所有回答汇总:", answers); } catch (err) { // 统一处理所有错误(超时、发送失败等) if (err.message.includes("time")) { await message.author.send("回答超时,问卷已终止"); } else { await message.author.send(`发生错误:${err.message}`); } console.error("问卷流程错误:", err); } }
3. 关键改动说明
- 用
async/await替代.then()链式调用:让异步逻辑更直观,避免回调地狱,同时方便统一捕获所有错误; - 修正
awaitMessages参数:第一个参数传入过滤函数,确保只收集当前用户的消息,第二个参数传入配置选项; - 使用
let x替代var x:确保每次循环迭代都有独立的变量作用域,避免迭代值混乱; - 统一错误处理:用外层
try/catch捕获所有异步错误,包括发送失败、回答超时等,彻底消除未处理的Promise拒绝警告; - 串行处理问题:确保上一个问题回答完成后再发送下一个,逻辑清晰,不会出现多个收集器同时运行的冲突。
内容的提问来源于stack exchange,提问作者Rijak Singh
相关产品推荐
相关产品推荐

