# 1、浏览器的进程

  • 每一个页卡都是一个进程 (互不影响)
  • 浏览器有一个主进程 (用户界面)
  • 每一个页卡里面都有一个渲染进程 (浏览器内核)
  • 网络进程 (处理请求)
  • GPU 进程 3d绘制

概念

进程:计算机默认是以进程为单位,进程是计算机调度的基本单位,进程中包含着线程

# 2、渲染进程(包含着多个线程)

  • GUI渲染线程(渲染页面的)
  • js引擎线程 (页面加载时,渲染js,它和页面渲染线程互斥)
  • 事件触发线程 独立的线程 EventLoop
  • 事件 click、setTimeout、ajax也是一个独立的线程

注意

因为GUI渲染线程和js引擎线程互斥,所以称js主线程是单线程的

# 3、宏任务和微任务

  • 宏任务 宿主(执行)环境提供的异步方法,都是宏任务。例如script脚本,UI渲染
  • 微任务 语言标准提供(语法要求)。例如promise,mutationObserver

# 4、宏微任务,及浏览器事件环执行流程图

注意

GUI渲染不是每次都执行的,如果默认没有调强制重绘的方法,它会积累到最后一起重绘,执行GUI渲染。

# 4-1 微任务和GUI渲染练习

<script>
  document. body. style. background = 'red'; 
  console. log(1)
  Promise. resolve(). then(()=>{

    console.log(2)
    document.body.style.background = 'yellow';

  })
  console. log(3); 
</script>

答案:1 -> 3 -> 2 -> red
(直接显示红色,黄色自始至终不会显示,因为渲染黄色在微任务里,微任务执行完毕后,才会GUI渲染)

# 4-2 定时器任务

<script>
  Promise. resolve(). then(() => {

    console.log('Promise1')
    setTimeout(() => {
      console.log('setTimeout2')
    }, 0);

  })
  setTimeout(() => {

    console.log('setTimeout1');
    Promise.resolve().then(() => {
      console.log('Promise2')
    })

  }, 0); 
</script>

答案:promise1 -> setTimeout1 -> promise2 -> setTimeout2
(无论宏微任务看哪个先加入到队列中,就执行哪个)

# 4-3 事件任务

<script>
  button. addEventListener('click', ()=>{

    console.log('listener1');
    Promise.resolve().then(()=>console.log('micro task1'))

  })
  button. addEventListener('click', ()=>{

    console.log('listener2');
    Promise.resolve().then(()=>console.log('micro task2'))

  })
  button. click(); 
</script>

答案:listener1 -> micro task1 -> listener2 -> micro task2
(按钮被点击的话,会立即执行,按照事件环,分别取出第一二个宏任务来执行)

区别于:

<script> 
  const a = () => {

    console.log('listener1');
    Promise.resolve().then(()=>console.log('micro task1'))

  }
  const b = () => {

    console.log('listener2');
    Promise.resolve().then(()=>console.log('micro task2'))

  }
  a() b()
</script>

答案:listener1 -> listener2 -> micro task1 -> micro task2
(事件立即被触发的话,按照js引擎线程的同步顺序依次执行,默认执行完之后,清空当前任务中的微任务队列)

# 4-4 async/await与定时器的输出顺序

<script> 
  async function async1() {

    console.log('async1 start');
    // 浏览器识别async + await await后面跟的是promise的话默认就会直接调用这个promise的then方法
    await async2();
    console.log('async1 end');
    // async2().then(()=>{
    //   console.log('async1 end');
    // })  
    // await async2();
    // console.log('async1 end')
    // new Promise((resolve,reject)=>resolve(async2())).then(()=>{
    //   console.log('async1 end');
    // });

  }
  async function async2() {

    console.log('async2');

  }
  console. log('script start'); 
  setTimeout(function() {

    console.log('setTimeout');

  }, 0); 
  async1(); 
  new Promise(function(resolve) {

    console.log('promise1');
    resolve();

  }). then(function() {

    console.log('promise2');

  }); 
  console. log('script end'); 
</script>

答案:
1、script start

  2、async1 start <br>
  3、async2 <br>
  4、promise1  <br>
  5、script end <br>
  6、async1 end <br>
  7、promise2  <br>
  8、setTimeout <br>

**微任务队列** [async1 end, promise2]
**宏任务队列** [setTimeout]

提示

async 返回的是一个promise (generator + co)
await => yield 如果产出的是一个promise,则会
1、首先执行await后面的函数 例如题中的 先执行 async2()
2、再执行async2. then()方法