Threading - 线程和定时器
EasyBot 提供了完整的定时器功能,支持延时执行和间隔执行,兼容标准的 JavaScript 定时器 API。
threading 命名空间
setTimeout()
创建一个定时器,在指定的延迟后执行回调函数。
语法: threading.setTimeout(callback: () => void, delay: number): number
参数:
callback- 要执行的回调函数delay- 延迟时间(毫秒)
返回值: 定时器ID
示例:
const timerId = threading.setTimeout(() => {
logger.info("3秒后执行");
}, 3000);
setInterval()
创建一个间隔定时器,每隔指定的时间执行回调函数。
语法: threading.setInterval(callback: () => void, interval: number): number
参数:
callback- 要执行的回调函数interval- 间隔时间(毫秒)
返回值: 定时器ID
示例:
const intervalId = threading.setInterval(() => {
logger.info("每5秒执行一次");
}, 5000);
clearTimeout()
清除定时器。
语法: threading.clearTimeout(timerId: number): boolean
参数:
timerId- 定时器ID
返回值: 是否成功清除
示例:
const timerId = threading.setTimeout(() => {
logger.info("这不会执行");
}, 1000);
const success = threading.clearTimeout(timerId);
logger.info(`清除成功: ${success}`);
clearInterval()
清除间隔定时器。
语法: threading.clearInterval(timerId: number): boolean
参数:
timerId- 定时器ID
返回值: 是否成功清除
示例:
const intervalId = threading.setInterval(() => {
logger.info("定期执行");
}, 1000);
// 10秒后停止
threading.setTimeout(() => {
const success = threading.clearInterval(intervalId);
logger.info(`停止间隔定时器: ${success}`);
}, 10000);
全局定时器函数
EasyBot 还提供了兼容标准 JavaScript 的全局定时器函数。
setTimeout()
全局版本的 setTimeout 函数,支持额外参数传递。
语法: setTimeout(callback: Function, delay?: number, ...args: any[]): number
参数:
callback- 要执行的回调函数delay- 延迟时间(毫秒),默认为0args- 传递给回调函数的参数
返回值: 定时器ID
示例:
// 基础用法
const timerId = setTimeout(() => {
logger.info("延时执行");
}, 2000);
// 传递参数
setTimeout((name, age) => {
logger.info(`Hello ${name}, you are ${age} years old`);
}, 1000, "张三", 25);
setInterval()
全局版本的 setInterval 函数,支持额外参数传递。
语法: setInterval(callback: Function, interval?: number, ...args: any[]): number
参数:
callback- 要执行的回调函数interval- 间隔时间(毫秒),默认为0args- 传递给回调函数的参数
返回值: 定时器ID
示例:
// 基础用法
const intervalId = setInterval(() => {
logger.info("定期执行");
}, 3000);
// 传递参数
setInterval((message) => {
logger.info(message);
}, 2000, "定时消息");
clearTimeout()
全局版本的 clearTimeout 函数。
语法: clearTimeout(timerId: number): void
参数:
timerId- 定时器ID
示例:
const timerId = setTimeout(() => {
logger.info("这不会执行");
}, 5000);
clearTimeout(timerId);
clearInterval()
全局版本的 clearInterval 函数。
语法: clearInterval(timerId: number): void
参数:
timerId- 定时器ID
示例:
const intervalId = setInterval(() => {
logger.info("定期执行");
}, 1000);
// 5秒后停止
setTimeout(() => {
clearInterval(intervalId);
}, 5000);
实用示例
延时发送消息
bus.on("group_message_event", (event) => {
if (event.RawMessage === "/remind") {
event.Context.Reply(new MessageChain().Text("我会在30秒后提醒你"));
setTimeout(() => {
event.Context.Reply(new MessageChain().Text("⏰ 时间到了!"));
}, 30000);
}
});
定期任务
// 每小时发送一次群公告
const hourlyAnnouncement = setInterval(() => {
const message = new MessageChain()
.Text("📢 每小时公告:请遵守群规,文明聊天!");
// 向所有群发送消息(需要根据实际情况获取群列表)
// context.SendGroupMessageAsync(selfId, groupId, message);
}, 3600000); // 1小时 = 3600000毫秒
倒计时功能
function startCountdown(context, selfId, peerId, seconds) {
let remaining = seconds;
const countdownInterval = setInterval(() => {
if (remaining <= 0) {
clearInterval(countdownInterval);
context.SendGroupMessageAsync(
selfId,
peerId,
new MessageChain().Text("⏰ 倒计时结束!")
);
return;
}
if (remaining <= 10 || remaining % 10 === 0) {
context.SendGroupMessageAsync(
selfId,
peerId,
new MessageChain().Text(`倒计时: ${remaining} 秒`)
);
}
remaining--;
}, 1000);
return countdownInterval;
}
// 使用示例
bus.on("group_message_event", (event) => {
if (event.RawMessage.startsWith("/countdown ")) {
const seconds = parseInt(event.RawMessage.split(" ")[1]);
if (seconds > 0 && seconds <= 300) { // 最多5分钟
startCountdown(event.AdapterContext, event.SelfId, event.PeerId, seconds);
}
}
});
定时清理任务
const activeUsers = new Map();
// 记录用户活动
bus.on("group_message_event", (event) => {
activeUsers.set(event.SenderId, Date.now());
});
// 每10分钟清理不活跃用户记录
setInterval(() => {
const now = Date.now();
const tenMinutes = 10 * 60 * 1000;
for (const [userId, lastActive] of activeUsers.entries()) {
if (now - lastActive > tenMinutes) {
activeUsers.delete(userId);
}
}
logger.info(`活跃用户数量: ${activeUsers.size}`);
}, 600000); // 10分钟
限流控制
const userLastMessage = new Map();
const MESSAGE_COOLDOWN = 5000; // 5秒冷却
bus.on("group_message_event", (event) => {
const userId = event.SenderId;
const now = Date.now();
const lastTime = userLastMessage.get(userId) || 0;
if (now - lastTime < MESSAGE_COOLDOWN) {
const remaining = Math.ceil((MESSAGE_COOLDOWN - (now - lastTime)) / 1000);
event.Context.Reply(
new MessageChain().Text(`请等待 ${remaining} 秒后再发送命令`)
);
return;
}
userLastMessage.set(userId, now);
// 处理用户命令
if (event.RawMessage === "/info") {
event.Context.Reply(new MessageChain().Text("这是信息"));
}
});
// 定期清理过期记录
setInterval(() => {
const now = Date.now();
for (const [userId, lastTime] of userLastMessage.entries()) {
if (now - lastTime > MESSAGE_COOLDOWN * 2) {
userLastMessage.delete(userId);
}
}
}, 60000); // 每分钟清理一次
注意事项
- 内存管理: 记得清理不再需要的定时器,避免内存泄漏
- 错误处理: 在定时器回调中添加错误处理
- 性能考虑: 避免创建过多的定时器
- 时间精度: 定时器的精度可能受到系统负载影响
- 函数差异: threading 命名空间的函数返回 boolean,全局函数返回 void