Discord.js bot如何编写递归异步函数定时拉取API检测新增帖子
Discord Bot 定时拉取API检查新帖解决方案
你遇到的问题核心有两点:一是latest_post变量作用域错误导致每次执行被重置,二是setInterval不适合异步任务容易出现请求堆积。以下是可直接使用的递归异步实现方案:
完整实现代码
const prefix = '你的命令前缀'; // 替换为你的实际命令前缀 const CHECK_INTERVAL = 30 * 1000; // 检查间隔,单位为毫秒,当前为30秒可自行修改 const API_URL = '你的API地址'; // 替换为实际请求的API链接 const NOTIFY_CHANNEL_ID = '你的通知频道ID'; // 替换为要发消息的Discord频道ID // 将latest_post声明在模块顶层,避免每次执行被重置 let latest_post = 12345; // 初始硬编码的最新帖子uid,首次运行后会自动更新 // 独立异步检查函数 async function checkNewPost() { try { const response = await fetch(API_URL); const body = await response.json(); // 直接用内置json()方法解析,无需手动parse const obj = body.data; const objId = obj[0].post_id; const objAuthor = obj[0].author; const objTitle = obj[0].title; // 修正原代码笔误:原代码未定义objTopic变量,此处使用取到的objId对比 if (objId > latest_post) { const notifyChannel = client.channels.cache.get(NOTIFY_CHANNEL_ID); if (notifyChannel) { await notifyChannel.send(`Found a new post by ${objAuthor}: ${objTitle}`); } // 直接更新顶层变量,不要加var/let/const声明,避免生成局部变量 latest_post = objId; } else { const d = new Date(); const n = d.toLocaleTimeString(); console.log(`No new posts yet at ${n}`); } } catch (error) { console.error('拉取API出错:', error); } finally { // 无论请求成功失败,处理完成后间隔指定时间发起下一次检查,避免请求堆积 setTimeout(checkNewPost, CHECK_INTERVAL); } } // Bot登录完成后启动轮询任务 client.on('ready', () => { console.log(`Bot已登录为 ${client.user.tag}`); checkNewPost(); }); // 原有的手动触发命令逻辑可以保留,不影响定时任务运行 client.on('messageCreate', async (message) => { if (!message.content.startsWith(prefix) || message.author.bot) return; const args = message.content.slice(prefix.length).split(/ +/); const command = args.shift().toLowerCase(); if (command === 'new') { try { const response = await fetch(API_URL); const body = await response.json(); const obj = body.data; const objId = obj[0].post_id; message.channel.send(`当前最新帖子ID为:${objId},已记录的最新ID为:${latest_post}`); } catch (error) { message.channel.send('Oops, there was an error fetching the API'); console.log(error); } } });
补充说明
- 如果你希望Bot重启后还能保留上次记录的
latest_post值,可以把该值持久化存储到本地JSON文件、数据库中,启动时读取即可,避免每次重启都回到初始硬编码值。 - 不要把检查间隔设置过短,避免触发API站点的限流规则。
内容的提问来源于stack exchange,提问作者HappyCod1337
相关产品推荐
相关产品推荐

