zoukankan      html  css  js  c++  java
  • 林大妈的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
      搞清楚基本的执行顺序即可,也不必要苛求每处都完全正确。
  • 相关阅读:
    494. Target Sum 添加标点符号求和
    636. Exclusive Time of Functions 进程的执行时间
    714. Best Time to Buy and Sell Stock with Transaction Fee有交易费的买卖股票
    377. Combination Sum IV 返回符合目标和的组数
    325. Maximum Size Subarray Sum Equals k 和等于k的最长子数组
    275. H-Index II 递增排序后的论文引用量
    274. H-Index论文引用量
    RabbitMQ学习之HelloWorld(1)
    java之struts2的数据处理
    java之struts2的action的创建方式
  • 原文地址:https://www.cnblogs.com/BlogOfMotherLyn/p/12318419.html
Copyright © 2011-2022 走看看