Handler 定时任务工具
GB.Handler 是一个零依赖的轻量级定时任务工具。它将浏览器原生 Timer API 封装为链式接口,可用于延迟执行、限次循环和持续轮询,并提供任务创建前后的生命周期回调。
快速开始
一个任务通常由“创建实例、配置参数、启动任务”三步组成。下面的任务会等待 1 秒,然后执行一次。
GB.Handler()
.delay(1000)
.start(() => {
console.log('1 秒后执行');
});
需要重复执行时,再通过 cycle() 指定次数;设置为 -1 时会持续运行,务必保存 start() 的返回值,以便后续停止。
安装与引入
浏览器直接引入
在业务脚本之前引入,之后即可使用全局方法 GB.Handler()。
<script src="https://cloud.m775.net/js/handler.js"></script>
npm 项目
npm i @gentbo/handler
import '@gentbo/handler';
理解执行流程
1. GB.Handler()创建一个独立的 Handler 实例。2. 配置使用 cycle、delay、before 和 after 描述任务行为。3. start(task)先执行 before,再创建原生定时器,随后执行 after。4. 等待 delay到达设定时间后执行 task;循环任务会按配置继续调度。before() 和 after() 围绕的是“定时器创建”过程,而不是每一次 task 执行。特别是 after() 不会等待循环任务全部完成。
控制执行次数
.cycle(cycle) 设置任务的理论执行次数。配置方法都会返回当前实例,可继续链式调用。
.cycle(-1)无限循环,直到通过返回的 Timer ID 主动停止。.cycle(0 / 1)执行一次,适合普通延迟任务。.cycle(n)当 n 大于 1 时,按指定次数循环执行。GB.Handler()
.cycle(3)
.delay(1000)
.start(() => {
console.log('执行');
});
// 第 1、2、3 秒各执行一次,随后结束
控制执行间隔
.delay(delay) 同时用于设置首次等待时间和循环间隔,参数单位为毫秒。内部最小值为 4ms;传入更小的值时,实际按 4ms 调度。
GB.Handler()
.cycle(-1)
.delay(1000)
.start(() => {
console.log('每秒执行一次');
});
前置与后置处理
.before(callback)注册前置回调,在创建定时器之前执行。.after(callback)注册后置回调,在定时器创建完成后执行;它不会等待循环任务全部结束。GB.Handler()
.delay(1000)
.before(() => {
console.log('准备创建任务');
})
.after(() => {
console.log('任务已创建');
})
.start(() => {
console.log('执行任务');
});
启动、返回值与停止
.start(task) 接收任务函数并立即完成定时器创建,返回对应的原生 Timer ID,而不是任务函数的返回值。请在组件卸载、页面切换或业务结束时清理仍在运行的任务。
const pollingTimer = GB.Handler()
.cycle(-1)
.delay(30000)
.start(() => {
refreshData();
});
// 停止无限循环任务
clearInterval(pollingTimer);
const delayedTimer = GB.Handler()
.delay(5000)
.start(() => console.log('5 秒后执行'));
// 取消尚未执行的延迟任务
clearTimeout(delayedTimer);
API 速查
GB.Handler()创建并返回新的 Handler 定时任务实例。.cycle(number)设置执行次数;-1 表示无限循环,0 或 1 表示执行一次。.delay(number)设置延迟或循环间隔,单位为毫秒,最小值为 4。.before(function)设置创建定时器前执行的回调。.after(function)设置创建定时器后执行的回调。.start(task: Function)启动任务并返回原生 Timer ID;task 内的返回值不会作为 start 的返回值。实用示例
倒计时
let count = 5;
GB.Handler()
.cycle(5)
.delay(1000)
.start(() => console.log(count--));
定时刷新数据
const timer = GB.Handler()
.cycle(-1)
.delay(30000)
.start(() => {
fetch('/api/data')
.then(response => response.json())
.then(data => console.log(data));
});
自动保存
const autoSaveTimer = GB.Handler()
.cycle(-1)
.delay(60000)
.start(() => {
saveDraft();
});
window.addEventListener('beforeunload', () => {
clearInterval(autoSaveTimer);
});
错误处理与计时限制
Handler 不会自动捕获任务中的异常。任务可能失败时,请在回调内部使用 try...catch,避免未处理异常影响页面逻辑。
GB.Handler().start(() => {
try {
runTask();
} catch (error) {
console.error(error);
}
});
浏览器性能、系统资源、页面是否位于后台以及 Timer 节流策略都会影响实际间隔。因此 cycle() 表示理论执行次数,delay() 也不保证毫秒级精确。页面进入后台后,实际间隔通常会大于配置值。
如果循环任务包含耗时的异步请求,下一轮可能在上一轮结束前开始。需要严格串行时,应在请求完成后再创建下一次延迟任务,而不是使用无限循环。
适用范围与兼容性
适合页面轮询、数据刷新、倒计时、状态检测、自动保存和普通延迟任务。不适合高精度计时、音视频同步和游戏引擎核心循环;逐帧动画优先使用 requestAnimationFrame。运行环境支持 ES2020、Class Private Field、setTimeout 与 setInterval 的现代浏览器。目标浏览器Chrome、Edge、Firefox、Safari,以及基于 Chromium 的常见内置浏览器。