如何利用 SharedWorker 优化 Vue3 项目中的数据共享
如何利用 SharedWorker 优化 Vue3 项目中的数据共享
引言
大家好,我是林三心。我的座右铭是用最通俗易懂的语言讲解最难的知识点,我始终相信基础是进阶的前提。
项目背景
最近,我的一个客户提出了一个非常有趣的优化建议。
我们的项目是基于 Vue3 开发的,客户习惯通过多个浏览器标签页同时打开相同的项目,以便于快速访问多个页面。例如,客户的两个页面(尽管外观上有显著不同)在某些功能上存在相似性:
这种做法可以理解,因为有些用户不喜欢在同一标签页中切换,他们觉得频繁切换很麻烦。
尽管这两个页面在外观上不同,但它们有一部分功能相似(但由于细节差异未封装成组件):
这部分相似的逻辑依赖于同一接口,并采用相同的数据处理逻辑,该过程耗时较长:
- 接口请求:3000ms,由于后端的数据获取逻辑复杂,返回的数据量庞大。
- 数据处理:300ms,前端需要进行数据处理。
因此,客户提出了这样一个优化请求:如果逻辑是相同的,是否可以让页面一共享数据给页面二、页面三、页面四呢?
优化点分析
在考虑客户的要求之前,我们先分析一下可能的优化方案。
由于接口请求
和数据处理
都是耗时且数据量大的操作,起初我打算将这些操作放入WebWorker
中执行。
然而,在客户提出的优化需求之后,我意识到不能使用WebWorker
,原因如下:
- 每个标签页的
WebWorker
都是独立的,无法共享数据。 - 即便使用
WebWorker + IndexedDB
进行数据缓存共享,依然很难共享数据状态
。
第一个原因比较容易理解,而第二个原因可能会让一些人困惑。为什么需要共享数据状态呢?
我们来看一下图示。数据状态的共享至关重要,因为页面二、页面三、页面四需要知道数据的状态,这有点像 Promise 的状态,可能是未缓存、缓存中、已缓存
。
以刚才的例子为例,有两种情况:
- 情况一: 页面一打开后,点击按钮进行数据请求和缓存,随后点击页面二的按钮,此时页面二可以获取到缓存的数据,这种情况没有问题。
- 情况二: 页面一点击按钮后 1 秒,再去点击页面二的按钮。此时页面二对页面一的数据状态一无所知,因此无法判断是发起请求,还是等待页面一的请求完成。
显然,共享数据状态是非常重要的。
采用 SharedWorker
最终,我放弃了WebWorker
,转而选择了SharedWorker
。
什么是SharedWorker
?可以将其理解为:SharedWorker
与WebWorker
类似,但它允许多个标签页共享。
当多个标签页连接同一个SharedWorker
时,SharedWorker
通过 port 管理每个标签页。可以说:每个标签页对应一个 port。
我们通过一个简单的案例来演示SharedWorker
,看看count
是否能够在两个页面间共享。
如图所示,count
成功被共享了。
接下来,我们将shared-worker.js
中的逻辑修改为请求数据和处理数据的代码。
然而,这样的写法并不能实现数据状态的共享!这实际上是进行了两次请求,优化效果并不明显。若页面一先点击再点击页面二,若实现了共享,理应同时接收到数据,但显然还没有达到最终效果。
因此,我们需要实现数据状态的共享,其实非常简单,只需利用Promise
即可。
最终的效果是,即使不同时点击,数据也能同时出现。
结语
感谢您的阅读,我是林三心。