副标题
前端定时任务的自我保护
需求背景
前端setInterval
会持续定时的执行一段任务,具体的api如下
setInterval(function, milliseconds, param1, param2, ...)
希望在function
失败时,有一个机制可以减少任务执行,或者不执行。
设计方案
- 代替原生
setInterval
- 允许3次错误尝试
- 3次错误尝试后,阶梯自增
milliseconds
- 正确访问后,回到初始
milliseconds
流程图
代码逻辑
/**
* @description 轮询熔断
* 1. 代替原生setInterval
* 2. 错误尝试
* 3. 阶梯递增时间周期
* 4. 正确访问后,降低时间周期至原始周期
*/
/**
* 使用方式
* @param callback 定时器执行的函数
* @param interval 定时器周期 毫秒数
* @returns timerId 定时器id,调用方可以手动关闭定时器
* fuseInterval(callback, interval)
*/
export default class FuseInterval {
step = 0 // 阶段
stage = [] // 存储定时周期,以2x,5x,10倍为单位
interval = null // 执行周期
callback = null // 定时到期,需要执行的函数
timeId = null // 当前定时器id
errorTimes = 0 // 失败次数
maxErrorTimes = 3 // 最大失败次数
constructor(callback, interval) {
// 可以根据自己的需求修改重试周期
this.stage = [interval * 2, interval * 5, interval * 10, interval * 20]
this.callback = callback
}
// 定时任务
setInterval() {
this.timeId = setInterval(async () => {
try {
await this.callback()
this.errorTimes = 0
// 如果请求成功,错误尝试重置为0
if (this.step > 0) {
this.step = 0
clearInterval(this.timeId)
return this.setInterval()
}
return this.timeId
} catch (error) {
// 判断是否超过单周期的最大请求次数
if (this.errorTimes > this.maxErrorTimes) {
// 清除定时器,step++,errorTimes赋值为0,开始新的需求
clearInterval(this.timeId)
this.errorTimes = 0
this.step++
return this.setInterval()
}
// 判断是否超过最大周期阈值
if (this.step > this.stage.length) {
clearInterval(this.timeId)
this.step = 0
this.errorTimes = 0
return this.timeId
}
this.errorTimes++
return this.timeId
}
}, this.stage[this.step])
}
}
// 调用方
const fuseInterval = new FuseInterval(async () => {
try {
return await this.task()
} catch (error) {
return Promise.reject(error)
}
}, 2 * 1000)
this.timer = fuseInterval.setInterval() // 返回一个定时器,给到调用方使用
更新记录:
- 同事纠正,熔断是立即行为。这个属于降级方案。故改下名字