From 16d5b0df95aaafc04816150c244f4d0fee3168f2 Mon Sep 17 00:00:00 2001 From: EYHN Date: Fri, 11 Apr 2025 02:32:12 +0000 Subject: [PATCH] fix(core): fix event timing in storage (#11628) --- packages/frontend/core/package.json | 1 + .../core/src/modules/storage/impls/storage.ts | 28 +++++++++++++------ yarn.lock | 1 + 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/packages/frontend/core/package.json b/packages/frontend/core/package.json index 9dbcf44245..a8e52d00fc 100644 --- a/packages/frontend/core/package.json +++ b/packages/frontend/core/package.json @@ -45,6 +45,7 @@ "cmdk": "^1.0.4", "core-js": "^3.39.0", "dayjs": "^1.11.13", + "eventemitter2": "^6.4.9", "file-type": "^20.0.0", "filesize": "^10.1.6", "foxact": "^0.2.43", diff --git a/packages/frontend/core/src/modules/storage/impls/storage.ts b/packages/frontend/core/src/modules/storage/impls/storage.ts index d17141dd29..9ce7814c92 100644 --- a/packages/frontend/core/src/modules/storage/impls/storage.ts +++ b/packages/frontend/core/src/modules/storage/impls/storage.ts @@ -1,4 +1,5 @@ import type { Memento } from '@toeverything/infra'; +import EventEmitter2 from 'eventemitter2'; import { Observable } from 'rxjs'; import type { @@ -8,6 +9,10 @@ import type { } from '../providers/global'; export class StorageMemento implements Memento { + // eventEmitter is used for same tab event + private readonly eventEmitter = new EventEmitter2(); + // channel is used for cross-tab event + private readonly channel = new BroadcastChannel(this.prefix); constructor( private readonly storage: Storage, private readonly prefix: string @@ -34,20 +39,27 @@ export class StorageMemento implements Memento { const first = json ? JSON.parse(json) : undefined; subscriber.next(first); - const channel = new BroadcastChannel(this.prefix + key); - channel.addEventListener('message', event => { - subscriber.next(event.data); - }); + const eventEmitterCb = (value: T) => { + subscriber.next(value); + }; + this.eventEmitter.on(key, eventEmitterCb); + + const channelCb = (event: MessageEvent) => { + if (event.data.key === key) { + subscriber.next(event.data.value); + } + }; + this.channel.addEventListener('message', channelCb); return () => { - channel.close(); + this.eventEmitter.off(key, eventEmitterCb); + this.channel.removeEventListener('message', channelCb); }; }); } set(key: string, value: T): void { this.storage.setItem(this.prefix + key, JSON.stringify(value)); - const channel = new BroadcastChannel(this.prefix + key); - channel.postMessage(value); - channel.close(); + this.eventEmitter.emit(key, value); + this.channel.postMessage({ key, value }); } del(key: string): void { diff --git a/yarn.lock b/yarn.lock index 7ed97016de..afd0ee6574 100644 --- a/yarn.lock +++ b/yarn.lock @@ -430,6 +430,7 @@ __metadata: cmdk: "npm:^1.0.4" core-js: "npm:^3.39.0" dayjs: "npm:^1.11.13" + eventemitter2: "npm:^6.4.9" fake-indexeddb: "npm:^6.0.0" file-type: "npm:^20.0.0" filesize: "npm:^10.1.6"