重写一下setInterval

73 阅读1分钟

讲解在同名B/D上都有,主要介绍一些跟业务无关的代码技巧

注: 部分内容主观性较大,一家之言姑且听之

本文主要介绍setInterval的二次封装

原文

这是项目中的某个封装,目的是处理,正在请求的问题,如使用中的描述

设置定时器1s执行,但如果1s时,请求没有完成,则忽略当前请求,代码可以实现,但可以优化下

function Timer() {
    this.flag = true
    this.setTime = (time, callback) => {
        this.clearTime = setInterval(() => {
            if (this.flag) {
                if (callback) callback()
            }
        }, time * 1000)
    }
}

const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms))
let t = Date.now()

// ... 使用
const timer = new Timer()
timer.setTime(1, async function () {
    timer.flag = false
    await sleep(2500)
    timer.flag = true
    console.log(Date.now() - t)
    t = Date.now()
})

setTimeout与setInterval

涉及一点这两个的区别,尤其是setInterval的调度问题

  • 长任务会爆栈吗?

setInterval是宏任务,假设定时1s执行1次,但里面的任务是长任务,1.1s才能执行完,此时,会出现宏任务无法退出的问题吗?

不会,如果定时器到了,但对应的任务没有执行完,这次注入会取消,但只限于长任务,对异步任务无效,也就是长任务与异步任务会有区别

解决方案,让两种任务表现一致

间隔方式如下如,这就是使用setTimeout代替setInterval

间隔1s | 执行时间 | 间隔1s | 执行时间 | 间隔1s

function setInterval1(promiseFn,time){
    setTimeout(async () => {
        // 需要判断是否为异步函数,省些
        await promiseFn()
        setInterval1(promiseFn,time)
    },time)
}

setInterval1(async function(){
    await sleep(2500)
    console.log(Date.now() - t)
    t = Date.now()
},1000)

其他可以添加的内容

  • 次数,setInterval1 需要决定可以请求几次
  • abort,整个响应可以取消
  • 时间可以为函数,描述随机时间
  • ...