perf(stores): defer safeStorage writes off the interaction path (#1941)
* perf(stores): defer safeStorage writes off the interaction path Session switches funnel every persisted store slice through safeStorage.setItem, and doing those large JSON.stringify writes synchronously blocked the main thread for over a second. Add a write-behind buffer that: - Defers each setItem/removeItem to a later task via setTimeout(0) so the click-to-paint path is not blocked. - Coalesces repeated writes to the same key into a single backing flush. - Serves pending values from memory so read-after-write stays consistent within the deferral window. - Flushes synchronously on pagehide/beforeunload/visibilitychange/freeze so deferred state survives tab close, reload, and the mobile freeze lifecycle. Adds a test covering write deferral, coalescing, and pending read serving. * fix(stores): defer persisted JSON serialization * fix(stores): defer direct safeStorage writes --------- Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
This commit is contained in:
committed by
GitHub
co-authored by
Bohdan Triapitsyn
parent
088a70fe5a
commit
1505274f94
@@ -129,7 +129,23 @@ const deferred = <T,>() => {
|
||||
};
|
||||
|
||||
mock.module('@/stores/utils/safeStorage', () => ({
|
||||
getDeferredSafeStorage: () => makeStorage(),
|
||||
getSafeStorage: () => makeStorage(),
|
||||
createDeferredSafeJSONStorage: () => {
|
||||
const testStorage = makeStorage();
|
||||
return {
|
||||
getItem: (name: string) => {
|
||||
const value = testStorage.getItem(name);
|
||||
return value === null ? null : JSON.parse(value);
|
||||
},
|
||||
setItem: (name: string, value: unknown) => {
|
||||
testStorage.setItem(name, JSON.stringify(value));
|
||||
},
|
||||
removeItem: (name: string) => {
|
||||
testStorage.removeItem(name);
|
||||
},
|
||||
};
|
||||
},
|
||||
}));
|
||||
|
||||
mock.module('@/stores/useProjectsStore', () => ({
|
||||
|
||||
Reference in New Issue
Block a user