一、同步与异步的概念

  1. 同步:
    必须等上面的任务或代码执行完成后才能执行
  2. 异步:
    无须等待上面的任务或代码执行完就可以执行,可以和上面的任务并行执行。

二、单线程与多线程概念

  1. 单线程:
    同一时刻只能做一件事。【同步】
  2. 多线程:
    同一时刻可以做多件事,【异步】

三、 js是单线程的(同步)

  1. 我们的JavaScript就其本身而言是单线程的。
  2. 任何时候,js引擎都是单线执行,即只会有一个线程运行JavaScript代码。
  3. 所以,我们会看到,正常情况下,js代码只会从上往下依次执行。

四、js借助浏览器多线程实现异步

虽然JavaScript是单线程的,但是在日常开发中,我们经常能写出多线程的异步代码。比如:定时器,ajax请求等常见功能。
这是为什么呢?
实际上,js是单线程的,但js的宿主环境(比如浏览器,Node)是多线程的,宿主环境通过某种方式(事件驱动)使得js具备了异步的属性。
即我们js引擎无法实现多线程,无法实现异步,但是我们可以借助浏览器内核来实现。这也就是我们平常写的定时器,ajax代码能异步执行的原因。

五、js+浏览器实现多线程异步过程

1. 一些基本概念
  1. 浏览器内核可以同时运行多个线程进行异步执行
  2. 这些线程在浏览器内核的控制下相互配合以保持同步。
  3. 浏览器内核至少会有三个常驻线程
    Js引擎线程【执行js代码】
    页面渲染线程【执行网页渲染操作】
    浏览器事件触发线程【执行事件监听】
  4. 浏览器内核中还会有一些临时线程,如:http请求线程,定时器
2. 关于任务队列(事件队列)

js是单线程语言,浏览器只分配给js一个主线程(js引擎线程),用来执行任务(函数),但一次只能执行一个任务,这些任务形成一个任务队列排队等候执行,就形成了任务队列。
所以js引擎线程一直在做一个工作,那就是不断的从任务队列里提取任务,放到主线程里执行。

3. 浏览器内核帮助js实现异步流程

前端的某些任务是非常耗时的,比如网络请求,定时器和事件监听,
如果让他们和别的任务一样,都老老实实的排队等待执行的话,执行效率会非常的低,甚至导致页面的假死。
所以,浏览器为这些耗时任务开辟了另外的线程,主要包括http请求线程,浏览器定时触发器,浏览器事件触发线程等,这些任务是异步的。

4. 注意事项:渲染线程和js主线程是互斥

在浏览器中,DOM页面渲染和js代码的执行,是单独的的线程,这里就要考虑到一个问题。
界面渲染线程是单独开辟的线程,是不是DOM一变化,界面就立刻重新渲染?
如果DOM一变化,界面就立刻重新渲染,效率必然很低,所以浏览器的机制规定界面渲染线程和js主线程是互斥的,主线程执行任务时,浏览器渲染线程处于挂起状态。【即页面被冻结】