JS的单线程和异步

2019-04-03  本文已影响0人  名字一定要够长才可爱

简述

JS触发异步原理

1. JS引入异步的原因

JS是单线程语言,浏览器只分配给JS一个主线程,用来执行任务(函数), 但一次只能执行一个任务,这些任务形成一个任务队列排队等候执行。但是前端的很多任务都是非常耗时的,比如http请求、定时器、事件监听等。如果让他们都按照同步原理顺序执行,那么执行效率会非常低,甚至导致页面的假死。

2. 浏览器模型

浏览器模型

3. 浏览器对JS异步的支持

浏览器内核允许多个线程异步执行,这些线程在内核控制下相互配合以保持同步。

三个常驻线程:

a). JavaScript引擎线程
b). 页面渲染线程
c). 浏览器事件触发线程

执行完就终止的线程

a). HTTP请求线程等
b). 定时触发器线程

4. 任务队列

顾名思义: 排着任务的队列。所谓任务就是webAPIs(浏览器为异步任务单独开辟的线程统一称为webAPIs)返回的一个个通知,让JS主线程在读取任务队列的时候得知这个异步任务已经完成,下一步该执行这个任务的回调函数了。主线程拥有多个任务队列,不同的任务队列用来排列来自不同任务源的任务。

5. 事件循环(event loop)

事件循环(event loop)

由三大模块组成: 函数调用栈、webAPIs、任务队列

执行过程:

1.主线程在遇到ajax或者setTimeout 这种异步操作时会交给浏览器的webAPIs,然后继续执行后面的代码,直到执行栈为空。

  1. 浏览器会在不确定的时间将完成的任务返回,排到相应的任务队列后。
  2. 执行栈为空时,主线程会到任务队列中去取任务,这些任务会告诉下一步应该执行那些回调函数。任务队列是具有优先级的,按照优先级顺序决定访问的先后循序。而优先级在不同的环境中又有所不同,不能一概而论。
  3. 每访问一个队列,执行栈会执行完这个任务队列的的所有代码,然后再取下一个任务队列需要执行的任务代码。如果在执行中遇到了属于当前任务的异步队列时,此次任务的返回不会排到当前的任务队列之后,因为这属于两次单独的事件循环,会被区分开来。
    就这样循环执行,直到三大块全为空,称为事件循环

6. AJAX请求是否异步

ajax请求内容的时候是异步的,当请求完成后,会触发请求完成的事件,然后把回调函数放到任务队列中,等到主线程执行该回调函数时还是单线程的。

7. 界面渲染线程是单独开辟的线程,是不是DOM一变化,界面就立刻重新渲染?

答案: 不是。
如果DOM一变化界面就重新渲染,效率必然很低,所以浏览器的机制规定界面渲染线程和主线程是互斥的,主线程执行任务时,浏览器渲染线程处于挂起状态。

上一篇 下一篇

猜你喜欢

热点阅读