zoukankan      html  css  js  c++  java
  • JS的运行机制到底是什么?

    JS的运行机制到底是什么?

    先给大家来段代码,看大家能否知道输出的结果

    console.log('1');
    
    setTimeout(function() {
        console.log('2');
        process.nextTick(function() {
            console.log('3');
        })
        new Promise(function(resolve) {
            console.log('4');
            resolve();
        }).then(function() {
            console.log('5')
        })
    })
    process.nextTick(function() {
        console.log('6');
    })
    new Promise(function(resolve) {
        console.log('7');
        resolve();
    }).then(function() {
        console.log('8')
    })
    
    setTimeout(function() {
        console.log('9');
        process.nextTick(function() {
            console.log('10');
        })
        new Promise(function(resolve) {
            console.log('11');
            resolve();
        }).then(function() {
            console.log('12')
        })
    })
    

    了解js的同步和异步

    先要明白js是单线程语言,所有的js多线程都是用单线程模拟出来的

    导图要表达的内容用文字来表述的话:

    • 同步和异步任务分别进入不同的执行"场所",同步的进入主线程,异步的进入Event Table并注册函数。
    • 当指定的事情完成时,Event Table会将这个函数移入Event Queue。
    • 主线程内的任务执行完毕为空,会去Event Queue读取对应的函数,进入主线程执行。
    • 上述过程会不断重复,也就是常说的Event Loop(事件循环)。

    我们不禁要问了,那怎么知道主线程执行栈为空啊?js引擎存在monitoring process进程,会持续不断的检查主线程执行栈是否为空,一旦为空,就会去Event Queue那里检查是否有等待被调用的函数。

    用我自己的话说:

    打开一个js代码,先执行同步任务,遇到异步任务,把异步任务放到队列中,等同步任务执行完之后,在执行异步任务,非常好理解

    其实这个不太准确,同步和异步是广义范围内的,如果要在精细一点,就分为宏任务和微任务,后面会讲

    那些是同步?那些是异步?

    异步:setTimeout(),setInterval(),Promise,process.nextTick(callback) 等

    同步:剩下的基本都是同步的

    宏任务和微任务

    • macro-task(宏任务):包括整体代码script,setTimeout,setInterval,dom事件,ajax请求
    • micro-task(微任务):Promise,process.nextTick,asycn/await

    结合图片和上面的文字可以看出

    • 整个script就是一个宏任务,所以先把script放入到宏任务中
    • 遇到setTimeout,setInterval,把它们也放到宏任务中。遇到Promise,process.nextTick,把它们放到微任务中
    • 先执行宏任务,执行完成,执行微任务,完成之后再执行宏任务,知道把所有的任务都执行完成

    接下来,看上面代码的输出结果

    安装宏任务和微任务的执行顺序,一点一点来

    1. 把js中所有是宏任务的代码都放到宏队列中,所有的微任务都放到微队列中,能直接输出的直接输出
      • 先输出1
      • 遇到setTimeout(),把它放到宏任务,有两个,先标记为set1,set2
      • 遇到process.nextTick,把执行的函数放到微任务
      • 遇到promise,只把.then的函数放到微任务,所以输出7
      • 第一步完成后输出1,7
    2. 然后执行微任务
      • 有两个微任务,要注意先后顺序,从上到下
      • 执行process.nextTick,输出6
      • 执行promise.then,输出8
      • 第二步完成后输出6,8
    3. 微任务执行完,在执行宏任务,有两个宏任务,set1,set2
      • 接下来和上面的操作是一样的,先执行宏任务set1
      • 输出2,4
      • 把promise.then和process.nextTick放入微任务
      • 执行微任务,输出3,5
      • 第三步完成后输出2,4,3,5
    4. 再执行宏任务set2
      • 输出9,11
      • 把promise.then和process.nextTick放入微任务
      • 执行微任务,输出10,12
      • 第四步完成后输出9,11,10,12

    最终结果1,7,6,8,2,4,3,5,9,11,10,12

    不知道各位小伙伴答案对不对呢?

  • 相关阅读:
    CentOS6.5配置MySQL主从同步
    CentOS6.5安装telnet
    linux 下安装Google Chrome (ubuntu 12.04)
    jdk w7环境变量配置
    JDBCConnectionException: could not execute query,数据库连接池问题
    注意开发软件的版本问题!
    linux mysql命令行导入导出.sql文件 (ubuntu 12.04)
    linux 下root用户和user用户的相互切换 (ubuntu 12.04)
    linux 下 vim 的使用 (ubuntu 12.04)
    linux 下安装配置tomcat-7 (ubuntu 12.04)
  • 原文地址:https://www.cnblogs.com/bnzw/p/14755881.html
Copyright © 2011-2022 走看看