开发Discord OsuApi命令遇Discord.js数据类型错误,求解决
Discord.js 参数错误排查与Osu API调用修复
问题描述
开发基于Discord的Osu API相关命令时,运行出现以下错误:
Discord.Js The "data" argument must be of type string or an instance of Buffer, TypedArray, or DataView. Received undefined
相关代码如下:
const { member, channel, content, guild } = message const cache = {} let data = cache[member.id] if (!data) { const e1 = new ME() .setTitle(`Fetching Data Please Wait`) .setColor("Random") .setTimestamp() .setFooter({ text: client.user.username, iconURL: client.user.displayAvatarURL() }) console.log("Fecting From DataBase") const msg = await channel.send({ embeds: [e1] }) await shi().then(async mongodb => { try { const result = await us.findOne({ _id: member.id }) if (!result) { const e2 = new ME() .setTitle("Aweeee~") .setColor(config.colors.no) .setDescription("No user found set user using 's!setuser <username or userid>' ") .setTimestamp() .setFooter({ text: client.user.username, iconURL: client.user.displayAvatarURL() }) await setTimeout(() => { msg.edit({ embeds: [e2] }) }, 5000); return } cache[member.id] = data = [result.text] } catch (err) { console.log(err) message.channel.send("Something bad happened sorry") } }) api.user .get(data) .then(data => { const dataJSON = JSON.stringify(data) fs.writeFileSync('user.json', dataJSON) const dataBuffer = fs.readFileSync('user.json') const stringJSON = dataBuffer.toString() const parseDATA = JSON.parse(stringJSON) console.log(parseDATA.username) channel.send("testing") }) }
错误原因分析
- 异步流程顺序错误:
await shi()仅等待shi()函数完成,但不会等待其then回调内的异步操作(数据库查询、data赋值)。导致调用api.user.get(data)时,data还未被赋值,仍是undefined。 - 数据类型错误:将
data赋值为数组[result.text],但Osu API的user.get()方法需要的是字符串类型的用户ID或用户名,数组不符合参数要求。 - 异常分支未终止后续逻辑:当数据库查询不到用户时,执行
return仅退出then回调,后续的API调用代码仍会执行,此时data为undefined,触发错误。 - 冗余文件操作:先将数据写入文件再读取解析,完全可以直接处理API返回的对象,无需额外IO操作。
修复方案
关键修改点:
- 改用
await替代then嵌套,确保异步操作顺序执行 - 修正
data赋值类型,直接使用result.text字符串 - 查询不到用户时,使用
return终止整个if (!data)分支的后续代码 - 移除冗余的文件读写逻辑,直接使用API返回的数据
修复后的代码:
const { member, channel, content, guild } = message const cache = {} let data = cache[member.id] if (!data) { const e1 = new ME() .setTitle(`Fetching Data Please Wait`) .setColor("Random") .setTimestamp() .setFooter({ text: client.user.username, iconURL: client.user.displayAvatarURL() }) console.log("Fetching From Database") const msg = await channel.send({ embeds: [e1] }) try { // 改用await替代then嵌套,确保流程顺序 const mongodb = await shi(); const result = await us.findOne({ _id: member.id }) if (!result) { const e2 = new ME() .setTitle("Aweeee~") .setColor(config.colors.no) .setDescription("No user found set user using 's!setuser <username or userid>' ") .setTimestamp() .setFooter({ text: client.user.username, iconURL: client.user.displayAvatarURL() }) // setTimeout无需await,本身不返回Promise setTimeout(() => { msg.edit({ embeds: [e2] }) }, 5000); // 终止后续代码执行 return } // 直接赋值为字符串,而非数组 cache[member.id] = data = result.text; // 确保data赋值完成后再调用API const apiData = await api.user.get(data); console.log(apiData.username); await channel.send("testing"); // 若需保存到文件,直接写入即可,无需重复读写 fs.writeFileSync('user.json', JSON.stringify(apiData)); } catch (err) { console.log(err); await channel.send("Something bad happened sorry"); } }
额外说明
- 若需要等待
setTimeout延迟后再执行后续逻辑,可将其封装为Promise:const delay = ms => new Promise(resolve => setTimeout(resolve, ms)); // 使用示例: await delay(5000); await msg.edit({ embeds: [e2] }); - 当前
cache变量在每次命令执行时都会重新创建,无法实现跨请求缓存,若需要持久化缓存,应将cache定义在函数外部。
内容的提问来源于stack exchange,提问作者Shiko Shintaro Ch.
相关产品推荐
相关产品推荐

