浏览器事件环

96 阅读3分钟

什么是进程?

进程是系统分配资源和调度的最小单位,多个进程之间是相互独立的 不会互相影响的,因此一个进程挂掉也不会影响其他进程

浏览器就是采用多线程模型,一个页面挂掉了也不会影响整个浏览器

每个网页都在隔离在自己的运行环境中,因此不同页面之间的代码是不能进行交互的

浏览器的进程组成

    • 浏览器的主线程 (管理浏览器的整体页面)
    • 渲染线程(每个页面一个,负责渲染页面的内容以及响应用户交互)
    • 网络线程 (加载资源的进程)
    • 插件线程(独立运行的)
    • GPU绘图线程(使用GPU进行加速图形渲染)
    • 事件触发线程 (事件环,调度任务)

就如同女娲捏人一样,先捏长条(主线程),然后画出四肢(渲染线程),在安个脑子(网络线程),再捏几个武器放一边(插件线程),再装点指令会吃会睡(事件触发线程),让脑子更聪明点(GPU渲染进程)

同步和异步的区别

同步和异步的区别在于是否需要等待这个操作的返回结果,需要等待的是同步, 不需要等待的是异步

异步任务划分

异步任务分为了 宏任务和微任务

宏任务(可以理解为浏览器自带的)

  • 定时器
  • setImmediate
  • 脚本执行,
  • ui渲染,
  • http请求,
  • MessageChannel,(消息通道)

微任务(可以理解为环境自带的)

  • Promise.then (处理异步逻辑)
  • Generator 函数
  • async/await
  • process.nextTick (node的异步)
  • ququeMicotask (微任务队列)
  • mutationObserver (h5提供的api)
  • requestAnimationFrame(动画,帧执行之前)
  • requestIDlecallback(动画,帧执行完毕后剩余的时间)

代码执行过程

  1. 先执行脚本解析,代码自上而下加载,遇到同步代码立即执行,遇到宏任务待它成功以后放入到宏任务队列中,遇到微任务则立即放入到微任务队列中
  2. 微任务执行完毕后,要检测"是否需要"渲染,浏览器有自己的刷新频率。 渲染一定是在宏任务之前做的。
  3. 宏任务执行的时候会产生一个微任务队列,
  4. 当宏任务执行完毕以后,会立即清空微任务队列,(清空的过程可能会产生 宏任务、微任务,产生的宏任务逻辑和上面一致,产生的微任务会被放到当前队列中)
  5. 微任务清空完毕以后,再取一个宏任务执行

宏任务和微任务的调度操作靠的就是eventLoop来实现的

举个栗子

console.log(1);
    async function fnOne() {
      console.log(2);
      await fnTwo(); // 右结合先执行右侧的代码, 然后等待
      console.log(3);
    }
    async function fnTwo() {
      console.log(4);
    }
    fnOne();
    setTimeout(() => {
      console.log(5);
    }, 2000);
    let p = new Promise((resolve, reject) => { // new Promise()里的函数体会马上执行所有代码
      console.log(6);
      resolve();
      console.log(7);
    })
    setTimeout(() => {
      console.log(8)
    }, 0)
    p.then(() => {
      console.log(9);
    })
    console.log(10);
    console.log(11);
    setTimeout(() => {
      console.log(12);
      let p = new Promise((resolve) => {
        resolve(13);
      })
      p.then(res => {
        console.log(res);
      })
      console.log(15);
    }, 0)
    console.log(14);