计时相关问题
使用闭包实现每隔一秒打印 1,2,3
js
// code1
const counter = (max) => {
for (let i = 1; i <= max; i++) {
setTimeout(console.log, i * 1000, i)
}
}
counter(3)
如果要求使用 Promise 实现,且要循环输出呢?
答案
js
const counter = (max) => {
const arr = Array.from({ length: max }, (x, i) => i)
arr.reduce((p, item) => {
return p.then(() => {
return new Promise((resolve) => {
setTimeout(() => resolve(console.log(item)), 1000)
})
})
}, Promise.resolve())
}
counter(3)
使用 setTimeout 模拟实现 setInterval
js
// 精简版本
function mySetInterval(handler, timeout = 0) {
setTimeout(() => {
arguments[0]()
mySetInterval(...arguments)
}, arguments[1] || 0)
}
js
// 支持清除定制器功能
function mySetInterval(handler, timeout = 0) {
let timer = {
value: 0,
valueOf: function () {
return this.value
}
}
function myTimer(...rest) {
timer.value = setTimeout(() => {
rest[0]()
myTimer(...rest)
}, rest[1])
}
myTimer(...arguments)
return timer
}
mySetInterval.clear = (timer) => {
clearTimeout(timer)
}
// testing
const timer1 = mySetInterval(() => {
console.log(111)
}, 1000)
const timer2 = mySetInterval(() => {
console.log(222)
}, 1100)
setTimeout(() => {
mySetInterval.clear(timer1)
}, 5000)
setTimeout(() => {
mySetInterval.clear(timer2)
}, 9000)
js
function mySetInterval(fn, timeout) {
// 控制器,控制定时器是否继续执行
var timer = {
flag: true
}
// 设置递归函数,模拟定时器执行。
function interval() {
if (timer.flag) {
fn()
setTimeout(interval, timeout)
}
}
// 启动定时器
setTimeout(interval, timeout)
// 返回控制器
return timer
}
// testing
const timer1 = mySetInterval(() => {
console.log(111)
}, 1000)
const timer2 = mySetInterval(() => {
console.log(222)
}, 1000)
setTimeout(() => {
timer1.flag = false
}, 5000)
setTimeout(() => {
timer2.flag = false
}, 9000)
浏览器中 setInterval 定义
long setInterval(in any handler, in optional any timeout, in any... args)
- 该方法返回的句柄是不变的 long 值(通过该句柄去取消定时器)
- 该方法的执行上下文必须是 window, WorkerUtils
格式:
mySetInterval(handler, ?timeout, ...args)
思考
为什么要用 setTimeout 模拟实现 setInterval?
setInterval 的缺陷是什么?
扩展: 我们能反过来使用 setinterval 模拟实现 settimeout 吗?
点我查看详细
js
const mySetTimeout = (fn, time) => {
const timer = setInterval(() => {
clearInterval(timer)
fn()
}, time)
}
如何实现一个 0ms 的 setTimeout?
setTimeout 为什么最小只能设置 4ms,如何实现一个 0ms 的 setTimeout?
点我查看详细
js
let timeouts = []
const messageName = 'zero-settimeout'
function setTimeoutZero(fn) {
timeouts.push(fn)
window.postMessage(messageName, '*')
}
function handleMessage(evt) {
if (evt.source == window && evt.data === messageName) {
if (timeouts.length > 0) {
const f = timeouts.shift()
f()
}
}
}
window.addEventListener('message', handleMessage)
window.zeroSettimeout = setTimeoutZero