async/await (异步)

2019-04-04  本文已影响0人  CRJ997

概述


async function(异步函数)是由Brian Terlson 提议的 ECMAScript 2017 新特性,表示一个函数内部有异步操作,实际可以说是生成器函数function* ()的语法糖,async具有自执行器。

声明方式

async function asyncfunction(){
    //函数体内容
}

let func = async function(){
  //函数体内容
}
...

返回值

async function 总是返回promise对象,这个promise对象只有在内部的所有await语句处理完成之后,其状态才会发生变化

来说说await

// 1.用try和catch语句包裹住可能出错的await语句
async function f() {
  try {
    await Promise.reject('出错了');
  } catch(e) {
  } 
  return await Promise.resolve('hello world');
}

f().then(v => console.log(v))// hello world

//2.在await的表达式后面用catch()进行异常的捕捉。
async function f() {
   await Promise.reject('出错了').catch(err=>console.log(err));
  return await Promise.resolve('hello world');
}

f().then(v => console.log(v))// 输出“出错了”和“hello world”

说说上面的红字部分

这个理解了比较长的时间,因为一道考察event loop的面试题

async function a1 () {
    console.log('a1 start')
    await a2()
    console.log('a1 end')
}
async function a2 () {
    console.log('a2')
}

console.log('script start')

setTimeout(() => {
    console.log('setTimeout')
}, 0)

Promise.resolve().then(() => {
    console.log('promise1')
})

a1()

let promise2 = new Promise((resolve) => {
    resolve('promise2.then')
    console.log('promise2')
})

promise2.then((res) => {
    console.log(res)
    Promise.resolve().then(() => {
        console.log('promise3')
    })
})
console.log('script end')
//正确的输出应该是:
script start
a1 start
a2
promise2
script end
promise1
a1 end
promise2.then
promise3
setTimeout

但是,关于为什么a1 end出现在promise1的后面我想了好久(大佬勿喷)。
然后经过几次尝试吧,我发现async遇到await之后,会把函数体中剩下的代码丢到微任务队列里面。然后我就解决了我的疑问。

分析一下上面的代码:
首先,主程序(第一个宏任务)执行,执行下列操作

  1. 输出script start
  2. 宏任务队列置入一个setTimeout
  3. 主程序中的微任务队列中置入一个微任务(console.log("promise1")
  4. 输出a1 start
  5. 立即resolve
  6. 把a1中剩下的语句置入主程序的微任务等待队列
  7. 输出a2
  8. 执行new Promise操作,输出promise2
  9. 主程序中的微任务队列中置入一个微任务(console.log(res))
  10. 输出script end
  11. 主程序执行完毕。开始执行微任务队列。

微任务队列执行:

  1. 输出promise1
  2. 输出a1 end
  3. 输出promise2.then
  4. 主程序的微任务等待队列中置入一个微任务(console.log("promise3"))
  5. 输出promise3

主程序的微任务队列执行完毕,执行下一个宏任务
输出setTimeout

程序执行完毕。

另外可以试着分析一下下面的代码的输出结果:

async function a1 () {
    console.log('a1 start')
    await a2();
    let i=18
    console.log(i)
    console.log('a1 end')
    await a3();
    console.log("aftera3");
    return new Promise((resolve,reject)=>{
        resolve("78");
    })
}
function a2 () {
    console.log('a2')
}
function a3 () {
    console.log('a4');
    Promise.resolve().then(()=>{
        console.log("hehe1");
    });
}

console.log('script start')

Promise.resolve().then(() => {
    console.log('promise1')
})
Promise.resolve().then(() => {
    console.log("extra message 1");
    console.log("extra message 2");
})
Promise.resolve().then(() => {
    console.log("extra message 3");
    console.log("extra message 4");
})
Promise.resolve().then(() => {
    console.log("extra message 5");
    console.log("extra message 6");
})

a1()

正确输出是:

script start
a1 start
a2
promise1
extra message 1
extra message 2
extra message 3
extra message 4
extra message 5
extra message 6
18
a1 end
a4
hehe1
aftera3
上一篇下一篇

猜你喜欢

热点阅读