setInterval 模拟 setTimeout
function mySetTimeout(fn, time) {let timer = nullfunction timeout() {fn()clearInterval(timer)}timer = setInterval(timeout, time)return {cancel: () => clearInterval(timer)}}var result = mySetTimeout(() => {console.log('mySetTimeout')}, 3000)setTimeout(() => {result.cancel()// console.log('提前执行了清空')console.log('延后执行了清空')}, 4000)
setTimeout 模拟 setInterval
function myInterval(fn, time) {let timer = null, isClear = false;function interval() {if (isClear) {isClear = falseclearTimeout(timer)return}fn()timer = setTimeout(interval, time)// console.log('timer - 1', timer)}timer = setTimeout(interval, time)// console.log('timer - 2', timer)// 返回一个清空定时器方法return {cancel: () => isClear = true}}let count = 0;let result = myInterval(() => {count++console.log('1 - myInterval', count)if (count === 3) {result.cancel()}}, 3000)
思路:
- 两个变量
timer和clear来存放当前定时器 ID,和清空定时器开关; - 声明
interval函数(重点),用来模拟setInterval; - 触发
interval函数执行,需要setTimeout。 - 返回清空定时器方法:
cancel;
注意:**timer**值是一直变的,需要取到最后一个**timer**值,用来清空最后一个定时器。
// 法二:function myInterval(fn, time) {let timer = null;function interval() {timer = setTimeout(interval, time)fn(timer)// console.log('timer - 1', timer)}timer = setTimeout(interval, time)// console.log('timer - 2', timer)return {cancel: (t) => clearTimeout(t)}}let count = 0;let result = myInterval((timer) => {count++// console.log('timer - 3', timer)if (count === 3) {result.cancel(timer)}}, 3000)
requestAnimationFrame 模拟 setInterval
function setInterval(callback, interval) {let timerconst now = Date.nowlet startTime = now()let endTime = startTimeconst loop = () => {timer = window.requestAnimationFrame(loop)endTime = now()if (endTime - startTime >= interval) {startTime = endTime = now()callback(timer)}}timer = window.requestAnimationFrame(loop)return timer}let a = 0setInterval(timer => {console.log(1)a++if (a === 3) cancelAnimationFrame(timer)}, 1000)
