我们都知道async-wait与generator的出现,是为了能让我们更好地去控制异步逻辑,避免回调函数的地狱
但是你确定真的完全掌握他俩的用法了吗?下面我会列出他们各自不同的用法,看下实际运行的结果与你的想法是否一致吧,废话不多说,开搞!
async-await
首先我们先看下async-await的不同用法,你可以自己先思考下每个使用场景的输出,看下是否与最终结果一致
场景一
1 | async function test() { |
程序运行过程如下:
- 执行test函数,遇见 await,执行后面的语句,打印出1,并让出执行权
- 执行test函数后面的
console.log(3)
,打印出3 - 返回test函数,执行await后面的
console.log(2)
,打印出2
所以最终输出为 1,3,2
场景二
1 | async function test() { |
程序运行过程如下:
- 执行test函数,遇见 await,执行后面的语句,将 setTimeout 的回调放入 宏任务队列 里
- 执行test函数后面的
console.log(3)
,打印出3 - 返回test函数,执行await后面的
console.log(2)
,打印出2 - 执行宏任务队列里的回调,打印出1
所以最终输出为 3,2,1,从这个例子我们可以看出await后面语句的优先级是高于宏任务的
场景三
1 | async function test() { |
程序运行过程如下:
- 执行test函数,遇见 await,执行后面的语句,将 Promise 的回调放入 微任务队列 里
- 执行test函数后面的
console.log(3)
,打印出3 - 执行微任务队列里的任务,打印出1
- 返回test函数,执行await后面的
console.log(2)
,打印出2
所以最终输出为 3,1,2,从这个例子我们可以看出await后面语句的优先级是 低于 微任务的
generator
这一节我们来看下generator函数的不同用法以及对应的输出,你可以自己先思考下每个使用场景的输出,看下是否与最终结果一致
场景一
1 | function* test(){ |
程序运行过程如下:
- 执行test函数,拿到 遍历器对象
- 调用遍历器对象的 next 方法,执行test函数语句,遇到 yield,会暂停函数语句的执行,并执行yield后面的 setTimeout,将回调函数放入宏任务队列等待执行
- 执行外部的
console.log(2)
,打印出2 - 执行宏任务队列里的回调,打印出1
所以最终输出为 2,1
场景二
1 | function* test(){ |
程序运行过程如下:
- 执行test函数,拿到 遍历器对象
- 调用遍历器对象的 next 方法,执行test函数语句,遇到 yield,会暂停函数语句的执行,并执行yield后面的 Promise.resolve,将then指定的回调函数放入 微任务队列 等待执行
- 执行外部的 setTimeout,将指定的回调函数放入 宏任务队列 等待执行
- 同步代码执行完毕,首先清空微任务队列的任务,即打印出1
- 然后执行宏任务队列里的任务,即打印出2
所以最终输出为 1,2
结语
async-await和generator的使用方式我们一定要烂熟于心,并且灵活运用,利用好它俩,是可以帮助我们很好地完成异步逻辑的编写,因此,对于它俩的掌握程度我认为一定要是精通,不然可能会在你做的项目中埋下大坑哦🤣~