美文网首页
async/await (异步)

async/await (异步)

作者: CRJ997 | 来源:发表于2019-04-04 17:18 被阅读0次

    概述


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

    声明方式

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

    返回值

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

    来说说await

    • await只能在async函数内部使用,表示这个部分有需要等待的操作。
    • await后面可以跟一个函数(普通函数或者async函数都可以)、表达式或者值。如果这些表达式或者函数并不产生或返回一个promise对象的话,await将这些值转换为一个立即resolve的promise对象。
    • 当执行async函数遇到await的时候,return语句会马上执行,async立即返回一个promise对象,这个promise的resolved值是return返回的值,并在await所在处的异步操作完成之后再接着执行async函数内部剩下的语句(中断时把函数体中剩下的语句丢到微任务等待队列中)。
    • 只要一个await后面的promise对象出现了reject,那么整个async函数便会中断执行。如果要制止出现这种情况,可以这样做:
    // 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
    

    相关文章

      网友评论

          本文标题:async/await (异步)

          本文链接:https://www.haomeiwen.com/subject/rqksmqtx.html