第一次棄用了 Web Worker ,因為它救不了我
背景
最近有一個客戶那邊提了一個很有意思的優(yōu)化點。
先說說背景吧,我們是一個 Vue3 的項目,客戶那邊習(xí)慣把同一個項目通過多個瀏覽 Tab 去打開,這樣就能很方便去使用多個頁面,比如下面這樣(簡單例子,實際是兩個長得很不一樣的頁面)。
圖片
其實客戶這么做也能理解,因為有些客戶就是不喜歡在同一個 Tab 標(biāo)簽頁中去切換菜單,他們覺得切來切去很麻煩。
雖然可能這兩個頁面長得很不一樣,但是有一小部分長得很相似的(但是還是有不同,所以沒封裝成組件)。
圖片
這部分相同的邏輯依賴的是同一個接口,同一個處理數(shù)據(jù)的邏輯,并且這兩個過程都很耗時:
- 請求接口:3000ms,因為后端取數(shù)據(jù)邏輯很復(fù)雜,返回數(shù)據(jù)量很大!
- 數(shù)據(jù)處理:300ms,前端拿到數(shù)據(jù)得處理一下。
所以客戶那邊提出了:既然都是同一個邏輯,那么能不能將頁面一的數(shù)據(jù)給頁面二、頁面三、頁面四用?。?/p>
分析優(yōu)化點
先拋開客戶提出的要求,我們先想想有什么優(yōu)化點。
接口請求 和 數(shù)據(jù)處理 都是比較耗時和數(shù)據(jù)量大的操作,所以我一開始是想放到 WebWorker 中去做的。
但是當(dāng)客戶提出優(yōu)化點后,我就發(fā)現(xiàn)不能用WebWorker 去做,原因如下:
- 1、每個 Tab 的WebWorker都是獨立的,無法進行數(shù)據(jù)共享。
- 2、就算用 WebWorker + IndexedDB 去做數(shù)據(jù)緩存共享,但是卻很難共享數(shù)據(jù)狀態(tài)。
第一個原因很容易理解,那第二個原因可能有些人不理解,為什么要共享數(shù)據(jù)狀態(tài)呢?
看下圖就懂了,為什么要共享數(shù)據(jù)狀態(tài)呢?因為你要讓頁面二、頁面三、頁面四這些頁面知道你數(shù)據(jù)的狀態(tài),有點類似于 Promise,狀態(tài)有 未緩存、緩存中、已緩存。
圖片
還是拿剛剛那個例子來說,兩種情況:
圖片
- 情況一: 頁面一打開并點擊按鈕進行數(shù)據(jù)請求處理和緩存,再去點擊頁面二的按鈕,那么頁面二肯定能拿到緩存的數(shù)據(jù),這種情況沒問題。
- 情況二: 頁面一點擊按鈕1秒后,去點擊頁面二的按鈕,這個時候頁面二是不知道頁面一的數(shù)據(jù)狀態(tài)的,所以頁面二不知道是要發(fā)起請求呢,還是要去等頁面一請求完呢?
所以共享數(shù)據(jù)狀態(tài)很重要。
SharedWorker
最終拋棄了 WebWorker,選擇了 SharedWorker。
圖片
SharedWorker是啥呢?你可以理解為: SharedWorker 類似于 WebWorker ,只不過SharedWorker 能讓多個 Tab 標(biāo)簽頁共享。
多個 Tab 連同一個SharedWorker 的時候, SharedWorker會通過 port 來管理每一個 Tab,可以說:一個 Tab 就是一個 port
我們通過一個小案例來演示一下 SharedWorker,我們看看 count能不能被兩個頁面共享。
圖片
圖片
可以看到 count被共享了!
圖片
現(xiàn)在我們把 shared-worker.js 里的邏輯改成請求數(shù)據(jù)和處理數(shù)據(jù)的代碼。
圖片
圖片
但是不對吧,這樣寫的話共享不到數(shù)據(jù)狀態(tài)啊??!這樣相當(dāng)于是請求了兩次,跟沒優(yōu)化一樣。。。頁面一先點,后再點頁面二,按理說如果共享了,應(yīng)該是同時出現(xiàn)數(shù)據(jù)才對,顯然現(xiàn)在還沒實現(xiàn)最終效果。
所以我們需要實現(xiàn)數(shù)據(jù)狀態(tài)共享,其實很簡單,利用Promise就行了!
圖片
這樣才是最終效果,不同時點擊,但是出現(xiàn)數(shù)據(jù)確是同時的。