主机参考:VPS测评参考推荐/专注分享VPS服务器优惠信息!若您是商家可以在本站进行投稿,查看详情!此外我们还提供软文收录、PayPal代付、广告赞助等服务,查看详情! |
我们发布的部分优惠活动文章可能存在时效性,购买时建议在本站搜索商家名称可查看相关文章充分了解该商家!若非中文页面可使用Edge浏览器同步翻译!PayPal代付/收录合作 |
本文带你了解微信小程序中的双线程模式,谈谈什么是小程序的双线程模式?为什么小程序没有使用浏览器的线程模型,而是使用了双线程模型,希望对大家有所帮助!
有过微信小程序开发经验的朋友应该都知道“双线程模式”的概念。本文简单梳理了双线模型的一些科普知识,小有所知。如有错误,请指正。
我曾经在“小程序云开发”团队工作。在一些国外的培训和技术分享中,我经常被问到这样一个问题:“微信小程序和网站的主要技术区别是什么?”就编程语言和范式而言,小程序开发与Web前端开发非常相似(如JavaScript语言、与HTML/CSS非常相似的WXML/WXSS等。),但它不直接使用原生前端技术。【相关学习推荐:小程序开发教程】
与网站相比,微信托管的小程序需要考虑安全、性能等因素,在保证小程序不会对微信App本身造成安全隐患的同时,尽量做到接近原生应用的性能和用户体验。这就是为什么小程序不直接使用浏览器的线程模型,而是必须自己获取一套双线程模型的两个主要原因。
那么什么是小程序的双线程模型呢?
了解一个新概念或新技术的最好方法是给它一个参考,所以要了解小程序的线程模型,首先要对浏览器的线程模型有一定的了解。
浏览器是多进程的,每个前端工程师在刚入行时可能都不止一次被面试官问到“如何理解前端单线程?”因为前端核心技能之一的JavaScript是单线程的,所以充分理解和掌握JS单线程的运行方式是一个前端工程师最基本的要求。然而,许多初学者很容易进入一个误区:错误地将“JavaScript单线程”理解为“浏览器单线程”。
实际上,浏览器的内部架构非常复杂,但在处理GUI渲染线程和JavaScript逻辑脚本线程时使用了互斥和阻塞的管理模式,这使一些开发人员产生了误解。
以Chrome浏览器为例。点击右上角的设置按钮,进入更多工具-》任务管理器。您将看到此弹出窗口:
可以看到Chrome已经启动了几个进程,包括浏览器进程、网络进程、GPU进程等。这些都是一般流程。请注意,上图中有两个tab进程。Chrome为每个标签打开了一个独立的渲染器进程,资源(CPU、内存等)。)和行为(UI、逻辑等。)彼此之间不共享,因此即使一个选项卡崩溃,也不会影响其他选项卡。
在每个tab进程中,浏览器会将不同的任务交给相应的线程。例如,GUI渲染线程负责将HTML渲染到可视化UI中。JavaScript引擎线程负责解析和运行JavaScript代码逻辑;定时触发线程负责处理setTimeout/setInterval定时器等。
GUI渲染线程和JavaScript引擎线程是互斥的,JavaScript在执行过程中会阻塞UI的渲染。即使脚本执行太长时间,它也会因为页面长时间无响应而崩溃。正是GUI渲染线程和JavaScript引擎线程之间的这种互斥和阻塞的线程管理方法,使得一些前端开发人员认为浏览器是单线程的。
那为什么JavaScript被设计成单线程的呢?
JavaScript的鼻祖只用了10天就创造了这种语言。起初,他的想法是在浏览器中提供一些简单的脚本逻辑来处理用户交互、DOM操作等。,因此在设计中必须遵循两点:
简单的语法;
操作机制简单。
在语法上,JavaScript借鉴了Java,但去掉了许多复杂的设置,如类型声明、模块系统(后来添加的)等。
在运行机制方面,JavaScript不像Java那样提供多线程能力,主要是为了避免多线程DOM带来的UI冲突。例如,如果有多个线程同时操作同一个DOM,浏览器如何判断哪个线程是最终UI效果的结果?这是一个经典的线程安全(也称为线程同步)问题。多线程编程领域有许多解决方案,例如添加锁机制,但这带来了更多的复杂性,这与JavaScript简单易用的设计初衷背道而驰。
这也解释了为什么GUI渲染线程和JavaScript引擎线程是互斥的:JavaScript代码有权修改DOM。
在执行JavaScript代码时,GUI渲染线程将被挂起,直到JavaScript引擎线程空闲,以避免渲染过程中JavaScript反复修改DOM造成不必要的渲染压力。等待JavaScript代码以互斥模式执行后,可以保证渲染是最终的执行结果。因此,浏览器的空闲时间也成为衡量网站性能的重要指标之一。空闲时间大多表示JavaScript逻辑不密集,DOM变化频繁。在这种情况下,浏览器可以更快更流畅地响应用户的交互行为,如下图所示:
后来,HTML5引入了Web Worker,它提供了多线程执行JavaScript代码的能力。但是,与其他编程语言不同的是,Worker线程不是与主线程并行的,而是Master-Slave多线程模型。
Worker中的JavaScript代码不能操作DOM,可以理解为线程安全。记住这一点,这是后来小程序双线程模型的重要基础。
那么为什么微信小程序不直接使用浏览器的线程模型呢?这需要从产品和技术的角度来比较小程序和网站之间的差异。
小程序为什么不用浏览器的线程模型?当我第一次接触applet开发时,我经常“不喜欢”它与Web相比的阉割能力,以及与Vue相比的简单语法。当时我几乎觉得,小程序是微信凭借庞大的用户群实现的技术垄断。
但随着对技术和产品的不断深入了解,我对小程序的态度也发生了变化,从“不喜欢”到钦佩,因为在充分了解小程序的产品定位后,我发现在小程序等产品场景中,双线程模式是最优解。小程序是一个什么样的产品?
小程序的主机是微信,但小程序版本的迭代是独立的,更新不依赖于主机,这和网站是一样的。换句话说,小程序继承了Web的一些优点,但它不是Web。目前,与Web相关的技术相当全面,它们可以承载一些非常大的应用程序,例如3D地图和游戏。
小程序的定位是小而美,用完就走。他们不追求微信中所有的Web功能,所以他们肯定比Web差。同时,他们拥有微信提供的一些原生能力,如原生组件、系统级和微信生态API等。
此外,“小程序-微信”和“网站-浏览器”的关系也不同。前者更接近于CodePen和JSFiddler等在线编程平台中每个程序案例(简称为案例)与平台之间的关系。
从技术角度来看,平台的核心考虑是在为案件提供足够容量的前提下,确保案件逻辑不会危及平台安全。想象一下,如果你能在CodePen上编写一个程序来获取CodePen的私人信息,它可能会在第二天崩溃并解雇所有员工。
在这种产品基调下,技术的选择之后是架构师和程序员的工作。
以CodePen为例。如果让你设计这样一个编程平台,你会使用什么技术?也许您想到的第一件事是使用iframe,因为您可以使用iframe中的所有Web功能。事实上,CodePen确实使用iframe来呈现程序的效果,但它不会将输入的JavaScript代码完全复制到iframe中运行,而是在经过一个编译过程后将代码注入到iframe中。这样做的出发点主要是基于安全考虑,在编译过程中会消除一些危险的代码;其次,它可以在平台中支持更多的语言,例如typescript。当然还有性能,这是iframe的老生常谈了,就不多说了。
因此,不仅应该使用iframe,还应该引入额外的JavaScript编译器。CodePen必须确保每种情况下的JavaScript代码都是线程安全的。最基本的是禁止程序操作CodePen网站的DOM。有两种方法可以实现这一点:
一个是webworker
另一种是使用影子DOM。
Web Worker是线程安全的,Worker中的JavaScript代码无法获取窗口和文档对象,因此无法操作DOM。此外,由于Worker的线程安全特性,Worker中的代码在运行过程中不会阻塞外部GUI渲染线程,两者可以并行。
影子DOM是Web组件规范的一部分。将ShadowRoot的模式设置为closed可以禁止获取ShadowRoot节点,因此无法操作其内部DOM。
两者相比,Shadow DOM的兼容性比Web Worker差,而且距离大规模使用的日期还很远,因此Web Worker的方案更符合实际。
这样就形成了一个简单的双线程模型:工作线程负责计算,结果通过postMessage传递给主线程,主线程负责渲染。
然而,该模型存在严重的性能问题。Web Worker会消耗大量资源,除了计算消耗外,与主线程的通信过程也会消耗大量性能。
有什么方法可以实现与Web Worker相同的线程安全性,同时以良好的性能兼顾良好的用户体验?这是微信小程序使用双线程模式的主要目的。
安全高效的双线程模型虽然以CodePen等编程平台作为类比,但小程序和CodePen的技术要求并不完全相同。主要区别在于小程序不需要支持所有的HTML标签,而只提供有限数量的UI组件。根据小程序的产品定位,我们可以得出结论,小程序的主要技术要求可以概括如下。任何新技术或架构都是为了解决特定问题而设计的,因此有必要了解小程序的主要技术要求。)
限制UI组件类型,只允许声明几个指定的组件。
小程序在声明组件时不使用原生HTML标签,只能使用微信提供的几个内置基本组件。当然,您也可以自定义组件,但这也是通过组合内置的基本组件来实现的。
确保逻辑线程的安全,不允许直接操作UI组件。
小程序更新UI的方式类似于MVVM框架,如Vue/React。JavaScript代码不能直接操作DOM(只是打个比方,实际上applet中没有DOM的概念),而是通过更新setState来异步更新UI,这将使用VDOM和高效的diff算法(这两点不是我们要讨论的,大家可以在课后自行搜索相关资料)。
能够不依赖微信在线更新。
小程序的主机是微信。如果是纯原生实现,那么小程序的版本更新必须依赖微信,和微信的代码一起分发,这肯定是不行的。如果是纯Web实现,很难保证安全性和性能。
小程序需要能够像Web一样在云中托管资源并独立更新;同时,它可以确保足够好的安全性和性能。所以最终小程序采用了混合架构模式:使用Webview渲染UI,使用类似Web Worker的独立线程运行逻辑,这就是双线程模型。
性能需要尽可能提高,以确保用户体验。
上面提到的基于Web Worker的简单双线程模型的性能是一个大问题。applet的双线程模型是一个独立的“主线程”,而不是使用Web Worker子线程,这可以确保相对较好的性能。
渲染线程和逻辑线程小程序的双线程是指渲染线程和逻辑线程,分别负责渲染UI和执行JavaScript代码。如下图所示:
呈现线程使用Webview来呈现UI。Webview是一个完整的类似浏览器的运行环境,具有运行JavaScript的能力。但是,小程序不会在Webview中运行逻辑脚本,而是将逻辑层分离到与Webview并行的线程中,并使用客户端提供的JavaScript引擎来运行代码。iOS的JavaScriptCore和Android是腾讯X5内核和IDE工具的nwjs提供的JsCore环境。
逻辑线程是一个只能运行JavaScript的沙盒环境,不提供与DOM操作相关的API,因此无法直接操作UI,只能通过setData更新数据的方式异步更新UI。
事件驱动的通信模式
注意上图中渲染线程和逻辑线程之间的通信方式。与Vue/React不同的是,小程序的渲染层和逻辑层之间的通信并不直接在它们之间传输数据或事件,而是由Native作为中间媒介进行转发。
整个过程是典型的事件驱动模式:
渲染层(也称为视图层)通过与用户的交互触发特定的事件事件;
然后将事件传递给逻辑层;
逻辑层再通过一系列逻辑处理、数据请求、接口调用等行为将处理后的数据传递给渲染层。
最后,呈现层将数据呈现为可视化UI。
这种数据驱动的UI模型是前端编程领域备受推崇的编程范式。如果你是一名拥有五年以上开发经验的前端开发人员,那么我相信你在刚接触这种模式时一定会有一些不适应,因为JavaScript操作DOM在之前几乎是一种“行业规则”,甚至许多针对前端入门的书籍、博客和教科书都是从DOM操作开始的。现在看来,这些真的过时了。
一方面,这种逻辑和渲染分离的线程划分模式可以确保运行在逻辑线程沙箱中的JavaScript代码是线程安全的;另一方面,由于渲染线程的计算量很小,因此可以确保快速响应用户交互行为,提高用户体验。
一般来说,与浏览器的线程模型相比,小程序的双线程模型解决或避免了Web Worker令人担忧的性能,同时实现了与Web Worker相同的线程安全性,从性能和安全性两方面都得到了提高。一般来说,双线程模式是小程序特定场景内的一种改进架构方案,受限于浏览器现有的进程和线程管理模式。
综上所述,在我看来,程序员的核心能力和竞争力并不是完全理解某种语言或框架的API,而是知道这些语言和框架的底层原理。对于一个小程序的开发人员来说,工作中技术问题的解决方案往往基于底层原则(或者更直白地说,当你在找工作面试时,没有人会问你小程序的语法)。
通过了解小程序的双线程模型的背景、设计和通信,我希望我们可以更深入地了解小程序的底层架构,如果在后续工作中有类似的场景,它也可以作为参考。当然,理解小程序的双线程模型并不是唯一的目标。在某种程度上,这些知识可以给日常开发工作带来一些启示,主要表现在:
在保证功能的前提下尽量使用结构简单的UI;
最小化JavaScript逻辑的复杂性;
最小化setData的调用频率及其承载的数据量。
更多编程相关知识请访问:编程视频!!
以上是对小程序中的双线程模型进行深入分析的细节。更多资讯请关注主机参考其他相关文章!
这几篇文章你可能也喜欢:
- 微信小程序翻译功能上线:现已支持18种语言
- 如何使用微信小程序中的车牌号输入法(如何使用微信小程序中的车牌号输入法进行打印)
- 微信小程序无法获取位置信息怎么办?(微信小程序无法获取位置信息)
- 微信小程序如何实现九宫格跳(如何在小程序中配置九宫格抽奖)
- 如何调节微信小程序的亮度?
本文由主机参考刊发,转载请注明:applet中多线程模型的深入分析(多线程工作) https://zhujicankao.com/104866.html
评论前必须登录!
注册