async/await & promise 让你一眼看穿 | 青训营笔记

62 阅读2分钟

这是我参与「第四届青训营 」笔记创作活动的第4天

引言

提到Promise,就不得不提一个东西,那就是async/awaitasync/await是一个很重要的语法糖,他的作用是用同步方式,执行异步操作。那么今天我就带大家一起实现一下async/await吧!!!

直接进入正题吧!

首先,你可以检测一下自己,如果你很清楚eventloop/async/await/promise这些东西呢,可以 break 啦~

async function async1() {
    console.log("async1 start");
    await async2();
    console.log("async1 end");
}

async function async2() {
    console.log("async2");
}

console.log("script start");

setTimeout(function() {
    console.log("setTimeout");
}, 0);

async1();

new Promise(function(resolve) {
    console.log("promise1");
    resolve();
}).then(function() {
    console.log("promise2");
});

console.log("script end");

输出结果:

script start
async1 start
async2
promise1
script end
promise2
async1 end
setTimeout

主要解析

async 做一件什么事情?

async是一个加在函数前的修饰符,被async定义的函数会默认返回一个Promise对象resolve的值。因此对async函数可以直接then,返回值就是then方法传入的函数。

  • 如果async关键字函数返回的不是promise,会自动用Promise.resolve()包装
  • 如果async关键字函数显式地返回promise,那就以你返回的promise为准

await 是在wait什么?

await等的是右侧「表达式」的结果

  • 如果不是 promise , await会阻塞后面的代码,先执行async外面的同步代码,同步代码执行完,再回到async内部,把这个非promise的东西,作为 await表达式的结果
  • 如果它等到的是一个 promise 对象,await 也会暂停async后面的代码,先执行async外面的同步代码,等着 Promise 对象 fulfilled,然后把 resolve 的参数作为 await 表达式的运算结果。

解析和分析过程

以上题为例:

  1. 直接打印同步代码 console.log('script start')
  2. 将setTimeout放入宏任务队列
  3. 调用async1,打印 同步代码 console.log( 'async1 start' )
  4. 接着到了await async2()
    (1)它先计算出右侧的结果
    (2)然后看到await后,中断async函数
    • 先得到await右侧表达式的结果。执行async2(),打印同步代码console.log('async2'), 并且return Promise.resolve(undefined)
    • await后,中断async函数,先执行async外的同步代码
  5. 被阻塞后,要执行async之外的代码
  6. 运行到promise.then() 这个是微任务,所以暂时不打印,只是推入当前宏任务的微任务队列中
  7. 打印同步代码 console.log('script end')
  8. 回到async内部,执行await Promise.resolve
  9. 宏任务1执行完成后,执行宏任务2(setTimeout)

这就是以上小题的解析,希望通过分析了解,让你对async await以及promise 有更深的了解,多做题多理解,多打代码,才能有更大的进步!