JS运行机制(学习笔记)

进程和线程:

进程是一个工厂,工厂之间相互独立

线程是工厂中的工人,多个工人(线程)协作完成任务

工厂内有一个或多个工人-工人之间共享空间

工厂的资源->系统分配的内存(独立的一块内存)

工厂之间相互独立->进程之间相互独立

多个工人协作完成任务->多个线程在进程中协作完成任务

工厂内有一个或多个工人->一个进程由一个或多个线程组成

工人之间共享空间->同一进程下的各个线程之间共享程序的内存空间

进程是cpu资源分配的最小单位(系统会给它分配内存)

单线程和多线程,都是指在一个进程内的单和多

浏览器是多进程

浏览器之所以能够运行,是因为系统给它的进程分配了资源(cpu,内存)

每打开一个tab页,就相当于创建了一个独立的浏览器进程

注意:打开多个tab页时,浏览器可能合并进程

浏览器包含进程:

Browser进程:浏览器的主进程,只有一个。作用:

负责浏览器界面显示,与用户交互。如前进后退

负责各个页面的管理,创建和销毁其他进程,包括地址栏,书签栏,前进后退等

将Renderer进程得到的内存中的Bitmap绘制到用户界面上

网络资源的管理,下载等

第三方插件进程:每种类型的插件对应一个进程,仅当使用该插件时才创建

GPU进程:最多一个,用于3D绘制等

浏览器渲染进程(浏览器内核)(Renderer进程,内部是多线程的):默认每个tab页一个进程,互不影响。主要作用:

页面渲染,脚本执行,事件处理等

在浏览器中打开一个网页相当于新起了一个进程(进程内有自己的多线程)

普通前端操作渲染进程(render进程)

主要常驻线程:

GUI渲染线程:

渲染浏览器界面,解析HTML,CSS,构建DOM树和RenderObject树,布局和绘制等。

重绘页面会引发回流时

注意:GUI渲染线程与JS引擎线程是互斥的,GUI更新会被保存在一个队列中等到JS引擎空闲时执行

JS引擎线程:

处理JavaScript脚本(如V8引擎)

解析JavaScript脚本,运行代码。

一个tab页中无论什么时候都只有一个JS线程在运行JS程序,所以时间都是排队等JS线程处理

事件触发线程

归属于浏览器,用来控制事件循环

执行setTimeOut、鼠标点击、ajax请求等时,会将对应任务添加到事件线程中,等待JS引擎处理

定时触发器线程

setInterval和setTimeOut所在的线程,计时完毕后添加到事件队列中,

setInterval精确地隔一段时间推入一个事件(但是,事件的实际执行时间不一定就准确,还有可能是这个事件还没执行完毕,下一个事件就来了)

多个setInterval的代码执行时间可能会比预期小(因为代码执行需要时间)

目前最佳方案是由setTimeOut模拟setInterval,或者直接用requestAnimationFrame

异步http请求线程

在XMLHttpRequest在连接后通过浏览器新开一个线程请求

检测到状态变更时,如果设置有回调函数,异步线程就产生状态变更事件,将这个回调放入事件队列中,等待JS引擎线程执行

Browser进程和浏览器内核(Renderer进程)的通信过程

Browser进程收到用户请求--获取页面内容--通过Renderer接口传递给Render进程

Renderer进程的Renderer接口收到消息--解释--交给渲染线程--开始渲染

渲染线程接收请求--加载并渲染网页(可能需要Browser进程获取资源和需要GPU进程帮助渲染)

JS线程操作DOM(回流、重绘)

Render进程将结果传递给Browser进程

Browser进程接收结果并绘制

浏览器内核中线程之间的关系

GUI渲染线程与JS引擎线程互斥

当JS引擎执行时GUI线程会被挂起,GUI更新则会被保存在一个队列中等到JS引擎线程空闲时立即被执行

JS阻塞页面加载

尽量避免JS执行时间过长,否则页面渲染会不连贯,会有页面渲染加载阻塞的感觉。

WebWorker(属于render进程下的一个线程)

针对cpu密集型计算,创建Worker时,JS引擎向浏览器申请开一个子线程(子线程是浏览器开的,完全受主线控制,而且不能操作DOM),并不意味着JS语言本身支持了多线程的能力,而是浏览器作为宿主环境提供了JS一个多线程运行的环境。

JS引擎线程与worker线程间通过特定的方式通信(postMessage API,需要通过序列化对象来与线程交互特定的数据)

ps:

把对象转换为字节序列的过程称为对象的序列化

把字节序列恢复为对象的过程称为对象的反序列化。

1) 把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中;
2) 在网络上传送对象的字节序列。

  在很多应用中,需要对某些对象进行序列化,让它们离开内存空间,入住物理硬盘,以便长期保存。比如最常见的是Web服务器中的Session对象,当有 10万用户并发访问,就有可能出现10万个Session对象,内存可能吃不消,于是Web容器就会把一些seesion先序列化到硬盘中,等要用了,再把保存在硬盘中的对象还原到内存中。

  当两个进程在进行远程通信时,彼此可以发送各种类型的数据。无论是何种类型的数据,都会以二进制序列的形式在网络上传送。发送方需要把这个Java对象转换为字节序列,才能在网络上传送;接收方则需要把字节序列再恢复为Java对象。

注意点:

  • 同源限制且非本地(加载的脚本必须来自网络)
  • 无法读取主线程所在网页的DOM对象,也不能获取document、window等对象,但是可以获取navigator、location(只读)、XMLHttpRequest、setTimeout等浏览器API
  • worker线程不能执行alert、confirm,但可以使用XMLHttpRequest对象发出ajax请求

SharedWorker(由独立的进程管理)

浏览器所所有页面共享,被多个Render进程共享

Chrome浏览器为SharedWorker单独创建一个进程来运行JavaScript程序,在浏览器中每个相同的JavaScript只存在一个SharedWorker进程,不管它被创建多少次。

浏览器渲染流程

浏览器输入url,浏览器主进程(Browser进程)接管,开一个下载线程,然后进行http请求

浏览器渲染流程

  1. 解析html建立dom树
  2. 解析css构建render树(将css代码解析成树形的数据结构,然后结合DOM合并成render树)
  3. 布局render树(Layout/reflow),负责各元素尺寸、位置的计算
  4. 绘制render树(paint),绘制页面像素信息
  5. 浏览器会将各层的信息发送给GPU,GPU会将各层合成,显示在屏幕上。

渲染完毕--load事件--JS逻辑处理

WebKit主流程:

Moziolla的Gecko呈现引擎主流程:

load事件与DOMContentLoaded事件的先后

DOMContentLoad触发时:仅当DOM加载完成,不包括样式表,图片。$(document).ready(function() { // ...代码... });

onload事件触发时:页面上所有的DOM,样式表,脚本,图片都已经加载完成。$(document).load(function() { // ...代码... }); 

CSS加载

css由单独的下载线程异步下载

css加载不会阻塞DOM树解析,但会阻塞render树渲染(渲染时需等css加载完毕,因为render树需要css信息)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值