• 林大妈的JavaScript进阶知识(二):JS异步行为


    JavaScript 是单线程执行的

    JavaScript运行在浏览器中。浏览器是多线程的,但只分配了其中一条给JavaScript,作为它的主线程。对于编码者来说,JavaScript是单线程的。因此JavaScript中存在以下几种异步行为:

    1. 事件绑定(addEventListener)
    2. 定时器(setTimeout、setInterval)
    3. AJAX(axios)、fetch
    4. 所有跟Promise的resolve、reject相关的行为(generator、async/await)

    JavaScript 异步执行情况

    其中WEB API会执行类似setTimeout的倒数或发送AJAX请求这样的操作,而得到的返回值则会加入Event Queue中等待主栈为空时压栈执行。
    练习题目

    // 以下的程序将会按照如何的顺序执行?
    async function async1 () {
        console.log('async1 start')
        await async2()
        console.log('async1 end')
    }
    
    async function async2 () {
        console.log('async2')
    }
    
    console.log('script start')
    
    setTimeout(() => {
        console.log('setTimeout')
    }, 0)
    
    async1()
    
    new Promise((resolve) => {
        console.log('promise1')
        resolve()
    }).then(() => {
        console.log('promise2')
    })
    
    console.log('script end')
    

    代码的基本分析:

    1. 第二到第十行,两个异步函数声明,不会输出东西
    2. 第十二到第二十七行,中间全部是函数执行的代码,可以把它看作主函数
    3. 第十二行是简单的输出语句
    4. 十四到十六行是一个setTimeout,通过前面的学习我们知道它会加入宏任务队列
    5. 第十八行是async1函数的执行,其中有一个async函数的嵌套,它把async2嵌套在了1中的await语句里
    6. 接着20行是一个Promise对象的声明,声明Promise对象需要传一个名为executor的参数,这个executor是会在声明的时候直接执行的,紧接着23行是一个then回调,通过前面的学习我们知道它会加入微任务队列
    7. 最后是一个普通的输出语句

    因此这题的难点就是在async语句的嵌套中。首先,根据前面的分析,因为前面都是函数声明,不会输出内容,代码会先输出script start,然后setTimeout加入宏任务队列。接下来进入异步函数async1,我们知道,异步函数本质上是generator的语法糖,因此异步函数会一直同步地执行到await语句执行完毕,并且把下面的代码放到微任务队列中,因此代码执行到此还会依次输出async1 start和async2。紧接着创建Promise对象时executor被执行,输出promise1,并把then放入微任务中,最后输出script end。理论上说,到此JS主线程已经执行完毕,也就是主栈中是空的,接下来就要分别看微任务和宏任务队列了。看微任务队列中现在有两个Task,按刚才所说的顺序是先是async1 end,再是promise2,但此处V8引擎版本不同执行情况不同,有的版本是按照队列顺序执行,有的是先执行Promise再执行await后的语句(但新版本的V8引擎是属于先执行Promise这种情况的,因此会输出promise2和async1 end)。这种现象可能是由于底层实现中await转化为promise语句是放在加入队列前还是加入队列后执行的关系,但无论如何它们两个微任务都必会在宏任务前执行,因此最后会输出宏任务的setTimeout。

    总结

    异步编程需要比较细地掌握它们三个微任务:

    1. async/await
    2. Promise
    3. generator
      搞清楚基本的执行顺序即可,也不必要苛求每处都完全正确。
  • 相关阅读:
    Lua函数
    Lua 造成的代码冗余太严重了, 这个现状怎么改善?
    Lua 造成的代码冗余太严重了, 这个现状怎么改善?
    Lua 错误处理方法
    Lua 错误处理方法
    C++引用、指针的选择
    C++引用、指针的选择
    Windows 7下VS2008升级补丁
    Windows 7下VS2008升级补丁
    天龙八部服务器端共享内存的设计(3/3)
  • 原文地址:https://www.cnblogs.com/BlogOfMotherLyn/p/12318419.html
Copyright © 2020-2023  润新知