electron的不同窗口(渲染進程)之間,如果想要同步localstorage中的狀態,只用pina+computer可以實現嗎?還是需要依賴electron的主進程廣播方式給不同的窗口,窗口通過監聽對應的channel來改變狀態?
比如我有homepage和dailpage兩個頁面。想對其中一個選項進行雙向同步。如何實現呢?
一種常見的做法是:
每個渲染進程,結合pinna來管理狀態,且同步到localstorage中(因為每個渲染進程之間是進程隔離的,必須通過統一存儲來進行狀態同步,即使是同一個子組件的兩個不同頁面),當某個窗口的 localstorage 發生變化時,通過 electron 的 ipc invoke 通知主進程。
主進程將這個變化廣播給所有其他窗口。其他窗口接收到這個channel後,更新自己的 localstorage 和 pinia 狀態。但是可能發現,這樣主-渲染進程,可能處理不好會造成廣播風暴。所以這時候還需要一個標誌來區分,這個狀態到低是我自己主動觸發改變的,還是我收到了事件被動改變的。
當然,你可能説用electron-store模塊來共享狀態,其實他倆之間的實現原理是類似的。
store的方案是主線程(默認)負責對監聽到的由渲染進程發起的update之後的state的更新廣播給渲染進程(包括主動觸發修改操作的渲染進程,但自己可以對其廣播忽略)。或者通過preload暴露出來sotre的方法。舉個例子:
渲染進程A修改了store數據:
- 渲染進程A通過IPC調用主進程的store.set()方法
- 主進程更新store數據並持久化到文件
- 主進程自動通知所有渲染進程(包括A和其他進程)數據已更新
- 所有渲染進程收到通知後更新本地狀態
當然你為實現響應式更新類型安全等高階特性,,就加一層pinia:
渲染進程A
↓ (action: setUser)
Pinia Store (A窗口本地)
↓ (調用 electronAPI.store.set)
electron-store (磁盤存儲)
↓ (觸發主進程的 onDidChange 或 ipc 消息)
主進程
↓ (廣播給其他窗口)
渲染進程B
↓ (收到消息,更新本地 Pinia)
Pinia Store (B窗口本地)
這是合理的方案嗎?還會有後續的問題就是如何處理: 渲染進程A需要區分"自己的操作"和"來自其他窗口的操作的事件"。這裏拋磚引玉,就用窗口id簡單過濾最有效,當前大佬們還有更多的基於操作id+版本控制(類似mvcc)、或者基於事件總線的發佈訂閲(區分local和listen)。