You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 05:25:45