理解浏览器的多线程,JavaScript的单线程以及小程序的双线程

作为一个前端开发者,相信大家都知道JavaScript是单线程的,但是有没有想过为什么呢,为什么是单线程呢,我们去面试的时候也经常会被问到怎么理解单线程,甚至有部分开发者错误地把JavaScript的单线程理解成了浏览器也是单线程,OK,我们今天就来正正经经地捋一捋。

卷起袖子,听我娓娓道来。。。

JavaScript是单线程

首先,JavaScript的单线程与它的用途有关,作为浏览器语言,JavaScript的主要用途是与用户互动以及操作DOM,这决定了它只能是单线程,否则会带来很复杂的同步问题,比如,假定JavaScript同时有两个线程,一个线程在某个DOM节点上添加内容,另一个线程删除了这个节点,这时浏览器应该以哪个线程为准呢?

虽然HTML5引入了web worker,允许JavaScript脚本创建多个线程,但是子线程完全受主线程控制,且不得操作DOM,所以,这个新标准并没有改变JavaScript单线程的本质。

浏览器是多线程

由于JavaScript是单线程,所有一些前端开发者误以为浏览器也是单线程,其实不是,浏览器是多线程的,浏览器为每个标签页开启了独立的渲染进程,每个进程之间的资源(CPU,内存等)和行为(UI,逻辑等)互不共享,所以即使某个标签页奔溃了也不会影响其他标签页。

而在每个标签页中,浏览器会把不同的工作交给对应的线程,比如GUI线程负责把HTML渲染成可视化的UI,JavaScript引擎线程负责解析和运行JavaScript代码逻辑,定时触发器线程负责处理setTimeout/setInterval定时器。

敲黑板,很多人以为setTimeout和setInterval是JavaScript的一部分,其实并不是,他们是运行时(最初是浏览器,后来node.js也提供了支持)提供的能力

我们知道,如果遇到网络慢的时候,有时候页面没办法完全加载出来,这是因为浏览器的GUI渲染线程和JavaScript引擎线程之间的互斥,阻塞的管理方式,JavaScript在执行期间会阻塞UI的渲染,甚至如果脚本执行时间太长会由于页面长时间无响应而奔溃。

为什么浏览器的GUI渲染线程和JavaScript引擎线程要互斥呢,本是同根生相煎何太急呀?

主要原因是,我们强大的JavaScript有修改DOM的权限!!!

当JavaScript代码被执行的时候,GUI渲染进程就会被挂起,等待JavaScript引擎进程空闲了再被执行,以免在渲染期间被JavaScript重复修改DOM造成不必要的渲染压力,采用互斥的的模式等待JavaScript代码执行完毕之后,可以保证渲染是最终的执行结果。

所以浏览器的空闲时长也成了衡量网站性能的重要指标之一,空闲时长多代表JavaScript逻辑密集以及DOM改动频率低,这种情况下浏览器可以更快速顺畅地响应用户的交互行为。

也是因为GUI线程和JavaScript引擎线程的这种互斥的方式,导致一些开发者误以为浏览器是单线程的。

微信小程序是双线程的

小程序的宿主是微信,但是小程序版本的迭代是独立的,升级更新不依赖宿主,这一点跟web网站是相同的,也就是说,小程序沿袭了web的某些优势,但是小程序并不是web,因为小程序的定位是小而美,用完就走,所以不追求在微信中实现全部的web能力,所以和web来比能力上肯定差一些,同时具备一些微信提供的原生能力,比如原生组件,系统级别和微信生态的API等等。

另外,小程序与微信的关系和网站和浏览器的关系不同,更接近codePen、JSFiddler这类在线编程平台中每个程序案例与平台的关系。

从技术的角度上,平台最核心的一个考量点是为案例提供足够能力的前提下,保证案例的逻辑不会危及平台的安全,说得直接点,就是你开发出来的小程序不能改动到宿主微信,也就是所谓的线程安全。

除了保证安全之外,还得考虑性能的问题,于是微信小程序根据以下几点技术需求采用了双线程的模型:

  • 限制UI组件类型,只允许声明指定的几个组件
  • 保证逻辑线程安全,不允许直接操作UI组件
  • 能够在线更新,不依赖微信

小程序的宿主是微信,如果使用纯native实现,那么小程序的版本更新必须依赖微信,跟微信的代码一起发版,这样肯定是不行的,如果是纯web实现,安全和性能就很难得到保障。

小程序需要既能够像web一样将资源托管在云端,更新独立;同时又能够保证足够好的安全性和性能,最终小程序采用了hybrid-混合的架构模式:使用webview渲染UI,使用类似web worker的独立线程运行逻辑,这就是小程序的双线程模型

小程序的双线程指的是渲染线程和逻辑线程,这两个线程分别承担UI的渲染和执行JavaScript代码的工作。

在这里插入图片描述
渲染线程使用webview进行UI的渲染呈现,webview是一个完整的类浏览器运行环境,本身具备运行JavaScript的能力,但是小程序并不是将逻辑脚本放到webview中运行,而是将逻辑层独立为一个与webview平行的线程,使用客户端提供的JavaScript引擎运行代码,,iOS的JavaScriptCore、安卓是腾讯X5内核提供的jsCore环境以及IDE工具的nwjs。

并且逻辑线程是一个只能够运行JavaScript的沙箱环境,不提供DOM操作相关的API,所以不能直接操作UI,只能够通过setData更新数据的方式异步更新UI。

基于小程序的双线程模式,我们在开发小程序中应该:
在保证功能的前提下尽量使用结构简单的 UI;
尽量降低 JavaScript 逻辑的复杂度;
尽量减少 setData 的调用频次和携带的数据体量

  • 5
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值