欢迎来到DIVCSS5查找CSS资料与学习DIV CSS布局技术!
多进程的浏览器
 
在提到单线程的JavaScript之前,先说一下浏览器的多进程做铺垫。
 
现代浏览器都是多进程的,以Chrome为例,如果想要查看浏览器的进程,可以打开菜单 - 更多工具 - 任务管理器
 
即便只打开一个网页,也会发现不止一个任务,在Chrome里,有如下进程
 
多进程的好处是享受操作系统里更好的隔离性,即便插件挂了,也只影响了插件的进程,对页面没有影响。像Docker启动的实例,其实也都是进程隔离。
 
但由于进程比较重,所以还有一个轻量级的线程可供使用,线程依附于进程。
 
单线程的JavaScript
 
我们知道JavaScript是一种单、异步非阻塞、解释型的语言。单线程指的是在JavaScript引擎中——无论是浏览器环境还是Node.js环境,执行JavaScript代码的线程只有一个。但不能认为整个运行环境的线程数只有一个,以浏览器来说,一般会有如下线程
 
JavaScript引擎线程 - 负责执行JavaScript,和GUI渲染线程是互斥的,因为JavaScript也能操作DOM,而UI的操作一般只能由一个线程来执行
 
事件触发线程 - 把事件任务放入事件队列,来源不光是UI事件,也可能是定时器、HTTP请求等
 
定时触发器线程 - 执行setTimeout和setInterval,到时后通过事件触发线程放入事件队列
 
HTTP请求线程 - 负责处理异步的Ajax请求,请求完成后,通知事件触发线程把回调放入事件队列
 
GUI渲染线程 - 解析HTML和CSS,然后将他们构建成DOM树和CSSOM树,进而合成渲染树,重排重绘也会调用起该线程;与JavaScript引擎线程是互斥的,当 JavaScript引擎线程在工作的时候,GUI 渲染线程会被挂起,GUI更新被放入在 JavaScript任务队列中,等待JavaScript引擎线程空闲的时候继续执行
 
在需要控制UI的客户端端技术中,都只能是由单个线程来控制界面变化,无论是Web还是iOS还是Android,都只能是由特定的运行线程来操作界面,如果多个线程的话反而会造成UI紊乱以及无谓的渲染开销,刚才也提到了JavaScript引擎线程由于能操作DOM,所以和GUI渲染线程也会形成互斥。
 
JavaScript虽然是单线程,但是它能做到异步非阻塞,速度嗖嗖的快,发出xhr请求后不需要等到它返回之后才继续往下执行,而是可以等到响应回来之后自动调用回调函数。JavaScript异步的实现靠的就是浏览器的多线程,当他遇到异步API时,就将这个任务交给对应的线程,当这个异步API满足回调条件时,该线程又通过事件触发线程将这个事件放入任务队列,然后主线程从任务队列取出事件继续执行。这个任务队列就是Event Loop。
 
在最新的HTML5中有了Web Worker,它能开出另一个线程,但是不涉及浏览器渲染等操作,也就是说它只是一个特殊的用作计算作用的线程,并受主线程管控。
 
同步与异步
 
在单线程环境下,代码分两种,一种是同步任务,一种是异步任务。如果不存在异步任务,那么代码永远是按照从上到下的次序执行,对于一些耗时、等待的场景则必然引起阻塞。假如有一个按钮点击之后从服务器下载数据,一旦阻塞,那么在服务器数据返回之前都无法对界面进行操作,必然引起非常糟糕的用户体验。
 
用一张图来表达同步任务和异步任务的不同执行方式。

如需转载,请注明文章出处和来源网址:http://www.divcss5.com/html/h64077.shtml