async/await

前端 0 314 0
发表于: 2020-07-21 15:34:32

简介: 暂无~

async 函数的返回值

下面解释 async 关键字做了什么:

  • 被 async 操作符修饰的函数必然返回一个 Promise
  • 当 async 函数返回一个值时,Promise 的 resolve 方法负责传递这个值
  • 当 async 函数抛出异常时,Promise 的 reject 方法会传递这个异常值

await 操作符做了什么

  • await 后的值 v 会被转换为 Promise
  • 即使 v 是一个已经 fulfilled 的 Promise,还是会新建一个 Promise,并在这个新 Promise 中 resolve(v)
  • await v 后续的代码的执行类似于传入 then() 中的回调
async function foo() {
    await bar()
    console.log('foo')
}
async function bar() {
    console.log('bar');
}
foo()
new Promise(resolve => {
    console.log('p1');
    resolve();
}).then(function () {
    console.log('p2')
})

//chrome 84环境下结果:bar,p1,foo,p2

根据提示

async function async1(){
  await async2()
  console.log('async1 end')
}

等价于

async function async1() {
  return new Promise(resolve => {
    resolve(async2())
  }).then(() => {
    console.log('async1 end')
  })
}

RESOLVE(non-thenable)

​ 如果await 后面直接跟的为一个变量,比如:await 1;这种情况的话相当于直接把await后面的代码注册为一个微任务,可以简单理解为promise.then(await下面的代码)。然后跳出async1函数,执行其他代码,当遇到promise函数的时候,会注册promise.then()函数到微任务队列,注意此时微任务队列里面已经存在await后面的微任务。

async function foo() {
    console.log('foo')
    // var res = await 1
    // console.log('foo_end')
    // 上两条代码等价于
    return new Promise(resolve => {
        resolve(1)
    }).then(() => {
        console.log('foo_end')
    })
}
async function bar() { }

foo()

new Promise(function (resolve) {
    console.log('p1')
    resolve();
}).then(function () {
    console.log('p2')
})

//foo,p1,foo_end,p2

RESOLVE(thenable)

​ async2() 返回一个 promise, 是一个 thenable 对象,RESOLVE(thenable) 并不等于 Promise.resolve(thenable) ,而 RESOLVE(non-thenable) 等价于 Promise.resolve(non-thenable),下面几个例子可证明:

let p1 = new Promise(resolve => {
    resolve(1)
})
p1.then(() => {
    console.log(2)
})
let p2 = Promise.resolve().then(res => {
    console.log(3)
})
p2.then(() => {
    console.log(4)
}).then(() => {
    console.log(5)
})
//2,3,4,5
// let p1 = new Promise(resolve => {
//     resolve(1)
// })
// 等价于
let p1 = Promise.resolve(1)
p1.then(() => {
    console.log(2)
})
let p2 = Promise.resolve().then(res => {
    console.log(3)
})
p2.then(() => {
    console.log(4)
}).then(() => {
    console.log(5)
})
//2,3,4,5
let p1 = new Promise(resolve => {
    let p3 = Promise.resolve()
    resolve(p3)
})
p1.then(() => {
    console.log(2)
})
let p2 = Promise.resolve().then(res => {
    console.log(3)
})
p2.then(() => {
    console.log(4)
}).then(() => {
    console.log(5)
})
//3,4,2,5
let p1 = new Promise(resolve => {
    let p3 = Promise.resolve()
    resolve(p3)
})
p1.then(() => {
    console.log(2)
})
let p2 = Promise.resolve().then(res => {
    console.log(3)
})
p2.then(() => {
    console.log(4)
}).then(() => {
    console.log(5)
})
//3,4,2,5
let p1 = new Promise(resolve => {
    let p3 = Promise.resolve()
    // resolve(p3)
    // 等价于
    Promise.resolve().then(() => {
        Promise.resolve(p3).then(() => {
            resolve();
        })
    })
})
p1.then(() => {
    console.log(2)
})
let p2 = Promise.resolve().then(res => {
    console.log(3)
})
p2.then(() => {
    console.log(4)
}).then(() => {
    console.log(5)
})
//3,4,2,5

RESOLVE(thenable) 和 Promise.resolve(thenable)的转换关系

new Promise(resolve=>{
  resolve(thenable)
})

会被转换成:

new Promise(resolve => {
  Promise.resolve().then(() => {
    thenable.then(resolve)
  })
})

或者:

new Promise(resolve => {
    Promise.resolve().then(() => {
        Promise.resolve(thenable).then(() => {
          resolve()
        })
    })
})

await 将直接使用 Promise.resolve()相同语义

原题:

async function foo() {
    await bar()
    console.log('foo')
}
async function bar() {
    console.log('bar');
}
foo()
new Promise(resolve => {
    console.log('p1');
    resolve();
}).then(function () {
    console.log('p2')
})

上述代码在chrome 70会最终编译成:

async function foo() {
    // return new Promise(resolve => {
    //     resolve(bar())
    // }).then(() => {
    //     console.log('foo')
    // })
    // 上面的代码等价于
    return new Promise(resolve => {
        Promise.resolve().then(() => {
            bar().then(resolve)
        })
    }).then(() => {
        console.log('foo')
    })
}
async function bar() {
    console.log('bar');
}
foo()
new Promise(resolve => {
    console.log('p1');
    resolve();
}).then(function () {
    console.log('p2')
})

// 结果:p1,bar,p2,foo

而在chrome 73中,会编译成:

async function foo() {
    const p = bar()
    Promise.resolve(p).then(() => {
        console.log('foo')
    })
}
async function bar() {
    console.log('bar');
}
foo()
new Promise(resolve => {
    console.log('p1');
    resolve();
}).then(function () {
    console.log('p2')
})

//结果:bar,p1,foo,p2

​ 因为await规范的更新,导致了await bar()在chrome 70和chrome 73最终编译成的代码不一样,因此,结果也会不一样,如果不适用await 关键字,直接用原生的Promise语句就不会出现这个问题(因为await的就是promise语法糖,会最终编译成promise语句)。

参考以下文章:

令人费解的 async/await 执行顺序

async await 和 promise微任务执行顺序问题

async/await 原理及执行顺序分析

知乎贺老师的解答

这一次,彻底弄懂 Promise 原理

Event Loop JavaScript

最后更新于:2021-02-16 21:13:29

欢迎评论留言~
0/400
支持markdown
Comments | 0 条留言
按时间
按热度
目前还没有人留言~