Discord.js递归等待用户输入函数出现极高延迟问题排查求助
问题根因分析
- 核心延迟原因:discord.js的
channel.awaitMessages默认会收集所有符合过滤规则的消息直到超时,你仅配置了60秒超时,没有添加max: 1参数指定收到1条消息就立即返回,导致每次都会等满60秒才返回结果,直接产生极高延迟。 - 逻辑异常问题1:
awaitMessages返回值为消息Collection集合,而非单个消息对象,你直接访问m.content必然得到undefined,永远无法命中cancel判断逻辑。 - 逻辑异常问题2:
awaitMessages函数定义仅接收1个参数,但你实际调用时传入了「询问Embed生成函数」和「校验函数」2个参数,参数完全错位,执行逻辑和设计预期完全不符。 - 笔误问题:
message.guild.channel.cache应为message.guild.channels.cache,makeError中发送Embed的参数写为embed应为复数embeds,递归调用时未传入正确的参数。
修复后完整代码
const Discord = require("discord.js"), { MessageEmbed } = Discord, ms = require("ms"); module.exports.run = async (client, message) => { async function awaitMessages(promptFunc, validateFunc) { // 先发送询问提示 await promptFunc(); // 配置max:1,收到1条符合条件的消息立即返回 const collected = await message.channel.awaitMessages({ filter: m => m.author.id === message.author.id, time: 60000, max: 1 }); // 处理超时无输入情况 if (collected.size === 0) { await message.channel.send("操作超时已取消"); return null; } // 取收集到的第一条消息 const m = collected.first(); if (m.content === "cancel") { await message.channel.send("cancelled"); return null; } const output = await validateFunc(m); // 校验不通过返回错误函数,发送后重新递归询问 if (typeof output === "function") { await output(); return await awaitMessages(promptFunc, validateFunc); } return output; } function makeWaitArg(argName, description) { const embeds = [new MessageEmbed() .setTitle(`Giveaway ${argName}`) .setDescription(description + " within the next 60 seconds.") .setColor("#2F3136") .setTimestamp() .setFooter("Create A Giveaway! | Type cancel to cancel.", message.author.displayAvatarURL())]; return () => message.channel.send({ embeds: embeds }) }; function makeError(title, desc) { const embeds = [ new MessageEmbed() .setTitle(title) .setDescription(desc || "") .setFooter("type cancel to cancel") ]; return () => message.channel.send({ embeds: embeds }) } const channel = await awaitMessages( makeWaitArg("Channel", "Please type the channel you want the giveaway to be in."), ({content}) => { if (message.guild.channels.cache.has(content)) return content; else return makeError("Channel", "That channel doesn't exist. Try Again."); } ); if (!channel) return; const prize = await awaitMessages( makeWaitArg("Prize", "Please send what you would like the giveaway prize to be"), ({ content }) => { if (content.length > 256) return makeError("Giveaway Prize Too Long.", "Please ensure the giveaway prize is less than 256 characters. Try again."); else return content; } ); if (!prize) return; const winnerCount = await awaitMessages( makeWaitArg("Winner Count", "Please send how many winners you would like the giveaway to have"), ({ content }) => { if (isNaN(content)) return makeError("Invalid Winner Count.", "Please provide valid numbers as the winner count. Try again."); else if (parseInt(content) > 15) return makeError("You can not have more than 15 winners per giveaway!") else return parseInt(content); } ); if (!winnerCount) return; const time = await awaitMessages( makeWaitArg("Time", "Please send how long you would like the giveaway to last"), ({ content }) => { if (!ms(content)) return makeError("Invalid Time.", "Please provide a valid time. Try again."); else return ms(content); } ); if (!time) return; // Start the giveaway };
修复说明
- 给
awaitMessages添加max: 1配置,收到1条用户消息立即返回,彻底解决等待超时导致的高延迟问题 - 修正了参数定义和传递逻辑,区分询问函数和校验函数,递归时正确传参
- 新增超时无输入的处理逻辑,避免无返回值异常
- 修正了所有语法笔误,调整了执行顺序,先发送提示再等待用户输入
- 对winnerCount新增了类型转换,直接返回数字类型方便后续逻辑使用
内容的提问来源于stack exchange,提问作者Zero
相关产品推荐
相关产品推荐

