js线程,微任务,宏任务,运行机制梳理

140 阅读2分钟

浏览器进程

进程是内存分配的最小单位

线程是执行的最小单位

没打开一个tab标签就是新启一个进程(内存是独立的)

浏览器内核

进程的渲染过程

  • GUI渲染线程(渲染DOM页面)
  • js引擎线程(运行js的)
  • 事件触发线程(js内的事件)
  • 定是触发器线程
  • 异步http请求线程

注意:这些都是属于浏览器的,与js引擎单线程一样都是属于浏览器的 GUI渲染线程与JS引擎线程是相互排斥的,所以JS如果执行时间过长就会阻塞页面

那么我们就可以理解了,我们经常遇到的问题,就是当js执行的时候遇到时间定时器,异步加载等,他们的输出结果会在页面所有js执行之后执行的问题了,就是当遇到时间定时器,异步加载等浏览器的事件触发线程就会触发他产生一个任务添加到js的任务队列中,同理异步http请求线程,事件触发线程也是一样的。

有进程产生的非js引擎的任务会分为宏,微任务队列

宏,微任务队列运行顺序

宏任务包括:setTimeOut,setInterval,setImmediate,I/O,用户交互操作,UI渲染

微任务包括:Promise,process.nextTick(nodejs),Ojbect.observe(不建议使用)

运行顺序:当js单线程执行完成之后就会去执行任务队列的内容。当宏微任务都有的时候,执行顺序是,先执行宏任务队列重的第一个任务,再执行全部的微任务,所以瞎卖呢代码输出结果是这样的

console.log(1)
      setTimeout(function() {
        //settimeout1
        console.log(2)
      }, 0);
      const intervalId = setInterval(function() {
        //setinterval1
        console.log(3)
      }, 0)
      setTimeout(function() {
        //settimeout2
        console.log(10)
        new Promise(function(resolve) {
          //promise1
          console.log(11)
          resolve()
        })
        .then(function() {
          console.log(12)
        })
        .then(function() {
          console.log(13)
          clearInterval(intervalId)
        })
      }, 0);
      
      //promise2
      Promise.resolve()
        .then(function() {
          console.log(7)
        })
        .then(function() {
          console.log(8)
        })
      console.log(9)

结果:1,9,7,8,2,3,10,11,12,13

注意:promise2运行的时候,它的两个then函数加入宏队列