身为一枚前端开发,有关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
*/