• JS中的执行机制(setTimeout、setInterval、promise、宏任务、微任务)


    1、执行机制

    JS 是单线程的,处理 JS 任务(程序)只能一个一个顺序执行,所以 JS 中就把任务分为了同步任务和异步任务。同步的进入主线程先执行,异步的进入Event Table并注册函数,当指定的事情完成时,Event Table会将这个函数移入事件队列Event Queue,等待主线程内的任务执行完毕,然后就会从事件队列 Event Queue 中读取对应的函数,进入主线程执行。

    除了广义的同步任务和异步任务,JS 对任务还有更精细的定义:

    • macro-task(宏任务):包括整体代码script,setTimeout,setInterval,setImmediate ,I/O ,UI rendering
    • micro-task(微任务):Promise,process.nextTick,MutationObserver

    微任务先于宏任务执行(除了一开始的整体代码 script)。执行过程中,不同类型的任务会进入对应的事件队列Event Queue,比如setTimeoutsetInterval会进入相同的Event Queue。

    1.1、执行优先级

    • 同步代码执行顺序优先级高于异步代码执行顺序优先级

    (注意:process.nextTick 是 node 中的方法,而在浏览器中执行时(比如在vue项目中),会退化成setTimeout,所以在浏览器中 process.nextTick 会比 Promise.then() 慢)

    1.2、总结

    总得来说,在 JS 中,先是执行整体的同步任务代码,遇到微任务就会将其放在微任务事件队列,遇到宏任务就会放在宏任务事件队列中。

    然后整体的同步任务代码执行完后,就会先执行微任务队列中的任务,等待微任务队列中的所有任务执行完毕后,此时才会从宏任务队列中找到第一个任务进行执行。该任务执行过程中,如果遇到微任务就会放到微任务队列中,等到该任务执行完后,就会查看微任务队列中有没有微任务,如果有就先执行完微队列中的任务,否则执行第二个宏任务。以此类推。

    例如:

    console.log('script start')
    
    async function async1() {
      await async2()
      console.log('async1 end')
    }
    async function async2() {
      console.log('async2 end')
    }
    async1()
    
    setTimeout(function() {
      console.log('setTimeout')
    }, 0)
    
    new Promise(resolve => {
      console.log('Promise')
      resolve()
    })
      .then(function() {
        console.log('promise1')
      })
      .then(function() {
        console.log('promise2')
      })
    
    console.log('script end')
    

     打印顺序为:

    script start => async2 end => Promise => script end => async1 end => promise1 => promise2 => setTimeout

    首先先来解释下上述代码的 async 和 await 的执行顺序。当我们调用 async1 函数时,会马上输出 async2 end,并且函数返回一个 Promise,接下来在遇到 await的时候会就让出线程开始执行 async1 外的代码,所以我们完全可以把 await 看成是让出线程的标志。

    然后当同步代码全部执行完毕以后,就会去执行所有的异步代码,那么又会回到 await 的位置执行返回的 Promise 的 resolve 函数,这又会把 resolve 丢到微任务队列中,接下来去执行 then 中的回调,当两个 then 中的回调全部执行完毕以后,又会回到 await 的位置处理返回值,这时候你可以看成是 Promise.resolve(返回值).then(),然后 await 后的代码全部被包裹进了 then 的回调中,所以 console.log('async1 end') 会优先执行于 setTimeout

    部分参考于:https://www.cnblogs.com/wenxuehai/p/12030199.html

  • 相关阅读:
    Ubuntu1804命令行安装vmtool
    Pyspider的基本使用
    HDU-4507
    CF264BGood Sequences
    CF285D.D. Permutation Sum
    我罗斯方块最终篇(Player类、Game类)
    ES学习(三)--查询
    ES学习(二)--增删改查
    GIT学习
    ES学习(一)--核心概念,NRT、索引、分片、副本
  • 原文地址:https://www.cnblogs.com/anu0823/p/13856832.html
Copyright © 2020-2023  润新知