JS中 sleep
方法的实现
目录
- 需求介绍
- 实现一:通过死循环阻塞执行
- 实现二:基于定时器延时
- 实现三:基于
Promise
的定时器 - 场景示例:红绿灯循环
- 下节预告
需求介绍
我们需要一个 sleep
函数来暂停程序的执行,从而实现延时效果。可以通过传入参数设置延迟时间,如下所示:
console.log('执行')
sleep(1000)
console.log('1000ms后执行')
期望结果:前面的程序执行完成后,间隔 1 秒再执行后面的代码。本文将实现该 sleep
方法。
实现一:通过死循环阻塞执行
由于 JS 是单线程的,只要在 sleep
时间内让程序处于阻塞状态,就能延迟后续程序的执行:
const sleep = timer => {
const curTime = Date.now()
while (Date.now() < curTime + timer) {}
}
console.log('执行:', new Date())
sleep(1000)
console.log('1000ms后执行:', new Date())
此方法通过 Date
计算当前时间是否达到延时时间。如果没有达到,程序会进入 while
循环,从而阻塞后续代码执行,实现延时效果。
缺点:这种方式会导致 JS 主线程被阻塞,无法处理其他任务(如其他代码块的执行、DOM 渲染等)。使用时要谨慎,尤其是在需要并行处理任务的场景中。
实现二:基于定时器延时
通过 setTimeout
延迟代码执行,这种方式可以简单实现延时效果:
const sleep = (act, timer) => {
setTimeout(act, timer)
}
const action = () => {
console.log('1000ms后执行:', new Date())
}
console.log('执行:', new Date())
sleep(action, 1000)
这种方式需要将延时执行的代码作为参数传递,维护性较差,且难以直接控制同步流程。
实现三:基于 Promise
的定时器
通过 Promise
,我们可以更加优雅地实现 sleep
功能:
const sleep = timer => {
return new Promise(resolve => {
setTimeout(resolve, timer)
})
}
console.log('执行:', new Date())
sleep(1000).then(() => {
console.log('1000ms后执行:', new Date())
})
使用 Promise
可以更灵活地处理异步流程。为了提高代码可读性,还可以结合 async/await
语法糖:
const sleep = timer => {
return new Promise(resolve => {
setTimeout(resolve, timer)
})
}
const action = async () => {
console.log('执行:', new Date())
await sleep(1000)
console.log('1000ms后执行:', new Date())
}
action()
这种方式让异步代码的可读性和可维护性大大提升。
场景示例:红绿灯循环
我们来实现一个红绿灯循环:红灯 15 秒、绿灯 15 秒、黄灯 2 秒。
const sleep = timer => {
return new Promise(resolve => {
setTimeout(resolve, timer)
})
}
const lightList = ['red', 'green', 'yellow']
const action = async index => {
switch (lightList[index]) {
case 'red':
console.log('当前是 红灯 ', new Date())
await sleep(15000)
break
case 'green':
console.log('当前是 绿灯 ', new Date())
await sleep(15000)
break
case 'yellow':
console.log('当前是 黄灯 ', new Date())
await sleep(2000)
break
}
index = (index + 1) % 3
action(index)
}
action(0)
在这个例子中,红灯、绿灯和黄灯依次循环,程序会根据不同的灯色等待相应的时间。