js实现sleep函数

461 阅读2分钟

身为一枚前端开发,有关Event Loop,宏任务,微任务这些问题,网络上有很多详细的解答,这里就不做过多解释,写这篇文章主要是记录一下async、await、promise以及实现一个sleep函数。只看sleep函数的实现可以直接拉到最后!!!

await的执行顺序问题

function logData1() {
  getData1().then((res) => {
    getData2(res).then((res) => {
      getData3(res).then((res) => {
        // todo
      })
    })
  })
}
​
async function logData2() {
  const data1 = await getData1()
  const data2 = await getData2(data1)
  const data3 = await getData3(data2)
}

项目中一个很常见的需求,一个请求接口的参数为另一个接口的返回值,遇到这种情况,采用上面logData1的方式,不难看出代码会有些臃肿(一般叫做地狱回调),而可以说async、await就是为了解决这种地域回调的问题,详情见logData2函数。

这里也不难看出如果如logData2形式,使用await发出getData1请求后,一定会阻塞下面代码getData2的运行,等待getData1运行完成后拿到返回值,才会继续发送getData2请求。

还有一个需要注意的地方,如下方代码所示:

console.log(123)
async function logData() {
  const data = await Promise.resolve("666")
  console.log(data)
}
​
logData()
console.log(456)

实际输出结果为123 ==> 456 ==>666,可以看出await的阻塞并不会阻塞logData函数作用域之外的代码执行。

sleep函数的实现

接下来先看题目:

const sleep = (duration) => {
  // TODO
}
​
const anyFunc = async () => {
  console.log("123") // 输出 123
  console.time()
  await sleep(300) // 暂停 300 毫秒
  console.timeEnd()
  console.log("456") // 输出 456,但是距离上面输出的 123 时间上相隔了 300 毫秒
}

我们已经知道await本身就会阻塞下面代码的执行,实际项目中,等待的时间就是后端接口返回的时间,那我们怎么去模拟这个等待返回这个过程,就可以借助setTimeout来实现。代码如下:

const sleep = (duration) => {
  return new Promise((resolve) => setTimeout(resolve, duration))
}
/**
  运行输出:
  123
  default: 301.973ms
  456
*/