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

简介

为何要弄清楚线程和任务(宏、微)。咱们常常会被问到一个问题,就是当settimeout和http请求回调还有promise的执行顺序。这里就涉及到了这些知识点。以及为何js过大影响dom渲染。html

本文适合有必定经验的前端人员,对js运行机制有必定了解。前端

一、浏览器进程

首先咱们要知道浏览器在渲染一个页面的过程种涉及到哪些工做原理。浏览器是多进程工做原理,什么是进程请自行学习(进程是内存分配的最小单位),一个进程又能够有多个线程(线程是执行的最小单位)。每打开一个tab标签就是新启一个进程(内存是独立的)。node

二、浏览器内核

知道了浏览器进程,那么说一下一个进程的渲染过程:web

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

注意:这些都是属于浏览器的与js引擎单线程同样是属于浏览器的segmentfault

GUI渲染线程与JS引擎线程是互斥的。因此会JS若是执行时间过长就会阻塞页面。promise

那么咱们就能够理解了,咱们常常遇到的问题,就是当js执行的时候遇到时间定时器、异步加载等,他们的输出结果会在页面全部js执行以后执行的问题了,就是当遇到到时间定时器、异步加载等浏览器的事件触发线程就会触发他会产生一个任务添加到js的任务对列内,同理异步http请求线程、事件触发线程也是同样的。浏览器

由进程产生的非js引擎的任务会分红宏、微两种任务对列。bash

三、宏、微两种任务对列运行顺序

宏任务包括有:setTimeOut、setInterval、setImmediate、I/O、用户交互操做,UI渲染网络

微任务包括有:Promise(重点)、process.nextTick(nodejs)、Object.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函数加入宏队列

四、Web Worker解决JS若是执行时间过长就会阻塞页面问题

Web Worker 的做用,就是为 JavaScript 创造多线程环境,容许主线程建立 Worker 线程,将一些任务分配给后者运行。具体怎么使用请自行学习。

Web Worker 有如下几个使用注意点:

  • 同源限制:分配给 Worker 线程运行的脚本文件,必须与主线程的脚本文件同源。
  • DOM 限制:Worker 线程所在的全局对象,与主线程不同,没法读取主线程所在网页的 DOM 对象,也没法使用document、window、parent这些对象。可是,Worker 线程能够navigator对象和lWorker 线程不能执行alert()方法和confirm()方法,但可使用 XMLHttpRequest 对象发出 AJAX 请求。ocation对象。
  • 通讯联系:Worker 线程和主线程不在同一个上下文环境,它们不能直接通讯,必须经过消息完成。使用worker.postMessage()通讯。
  • 脚本限制: Worker 线程不能执行alert()方法和confirm()方法,但可使用 XMLHttpRequest 对象发出 AJAX 请求。
  • 文件限制:Worker 线程没法读取本地文件,即不能打开本机的文件系统(file://),它所加载的脚本,必须来自网络。

结尾

本文是是本身学习笔记,若有看不懂的可参考如下连接。

参考文章连接以下:

一、浏览器以及js运行原理:segmentfault.com/a/119000001…

二、宏观任务和微观任务原理:juejin.im/post/5da742…

三、Web Worker使用:www.ruanyifeng.com/blog/2018/0…

相关文章
相关标签/搜索