Discord Bot时间戳延迟问题:定时网站状态更新异常
问题:Discord Bot状态更新时间戳延迟问题
我开发了一个基于JavaScript的Discord Bot命令,每5秒更新一次网站的在线/离线状态,同时显示当前时间戳。但运行一段时间后,时间戳开始出现数分钟的延迟,最终甚至会延迟数小时。我推测该问题与5秒一次的状态检查逻辑有关。
const tcpp = require('tcp-ping'); const { EmbedBuilder } = require('discord.js'); let statusMessage = null; module.exports = { checkWeb: async (client) => { try { const website = { name: "mysite", url: "mysite.com", port: 80 }; tcpp.probe(website.url, website.port, function(err, available) { if (err) { throw new Error(`Error probing website: ${err}`); } const status = available ? "🟢 Online" : "🔴 Offline"; const color = available ? "#00FF00" : "#FF0000"; const description = available ? `The ${website.url} is up and running.` : `The ${website.url} is offline.`; const embed = new EmbedBuilder() .setTitle(`Status of ${website.name}`) .setDescription(`${description}\n\nStatus: ${status}\n\u200B`) .setThumbnail('https://i.imgur.com/AfFp7pu.png') .setTimestamp() .setColor(color); if (!statusMessage) { client.channels.cache.get('1232582546932633610').send({ embeds: [embed] }) .then(message => { statusMessage = message.id; }); } else { client.channels.cache.get('1232582546932633610').messages.fetch(statusMessage) .then(message => { message.edit({ embeds: [embed] }); }) .catch(console.error); } }); } catch (error) { console.error(`Error checking website status: ${error}`); } finally { setTimeout(() => module.exports.checkWeb(client), 5 * 1000); } } };
问题原因及修复方案
核心问题
你的代码逻辑存在异步任务堆积的问题,直接导致时间戳延迟:
tcpp.probe是异步回调操作,完成时间受网络状态影响(比如网络卡顿时耗时远超5秒),但你不管它是否执行完成,都会在5秒后立刻触发下一次checkWeb调用。- 多次未完成的异步请求叠加,后续的状态检查会被前面的请求阻塞,时间戳自然会越来越滞后。
修复步骤
1. 把回调式的tcpp.probe改成Promise化写法
避免嵌套回调,让异步流程更可控:
// 封装tcpp.probe为Promise const probeWebsite = (url, port) => { return new Promise((resolve, reject) => { tcpp.probe(url, port, (err, available) => { if (err) reject(err); else resolve(available); }); }); };
2. 等待异步操作完成后再触发下一次检查
把递归setTimeout移到所有异步操作完成后,确保每次检查周期是"完成本次检查→等待5秒→开始下一次检查":
module.exports = { checkWeb: async (client) => { try { const website = { name: "mysite", url: "mysite.com", port: 80 }; // 等待网站探测完成 const available = await probeWebsite(website.url, website.port); const status = available ? "🟢 在线" : "🔴 离线"; const color = available ? "#00FF00" : "#FF0000"; const description = available ? `${website.url} 运行正常。` : `${website.url} 已离线。`; const embed = new EmbedBuilder() .setTitle(`${website.name} 状态`) .setDescription(`${description}\n\n状态:${status}\n\u200B`) .setThumbnail('https://i.imgur.com/AfFp7pu.png') .setTimestamp() .setColor(color); if (!statusMessage) { const message = await client.channels.cache.get('1232582546932633610').send({ embeds: [embed] }); statusMessage = message.id; } else { const message = await client.channels.cache.get('1232582546932633610').messages.fetch(statusMessage); await message.edit({ embeds: [embed] }); } } catch (error) { console.error(`检查网站状态出错:${error}`); } finally { // 本次所有操作完成后,再设置下一次检查 setTimeout(() => module.exports.checkWeb(client), 5 * 1000); } } };
3. 额外优化建议
- 给
messages.fetch和频道消息操作添加超时处理,避免单个请求卡住整个循环。 - 可以考虑用
setInterval替代递归setTimeout,但要注意如果异步操作耗时超过5秒,依然会出现任务堆积,因此更推荐用Promise+递归的模式。
内容的提问来源于stack exchange,提问作者razor60
相关产品推荐
相关产品推荐

