fix: await initial market synchronization

This commit is contained in:
wxs
2026-07-17 16:06:51 +08:00
parent 01efa9f847
commit 8ca9f95583
2 changed files with 149 additions and 33 deletions
+70 -33
View File
@@ -225,11 +225,13 @@ export function createMarketController(options: CreateMarketControllerOptions) {
});
let activeSort: MarketSortState | undefined;
let isDisposed = false;
let isSyncRunning = false;
let isSyncScheduled = false;
let lastKnownPageSignature = "";
let needsResync = false;
let scheduledSyncTimeoutId: number | null = null;
let activeSyncPromise: Promise<void> | null = null;
let scheduledSyncPromise: Promise<void> | null = null;
let resolveScheduledSync: (() => void) | null = null;
let rejectScheduledSync: ((reason?: unknown) => void) | null = null;
const selectedAuthorIds = new Set<string>();
let toolbar: ReturnType<typeof ensurePluginToolbar> | undefined;
let cachedFavoritesState: FavoritesStateV1 | undefined;
@@ -533,7 +535,9 @@ export function createMarketController(options: CreateMarketControllerOptions) {
const ready = (async () => {
await runSyncCycle();
await refreshFavorites();
const initialScheduledSync = scheduledSyncPromise;
await waitForDomSettled();
await (initialScheduledSync ?? activeSyncPromise ?? scheduledSyncPromise);
})();
return {
@@ -544,6 +548,10 @@ export function createMarketController(options: CreateMarketControllerOptions) {
options.window.clearTimeout(scheduledSyncTimeoutId);
scheduledSyncTimeoutId = null;
}
resolveScheduledSync?.();
scheduledSyncPromise = null;
resolveScheduledSync = null;
rejectScheduledSync = null;
disposeFavoriteRowPickers(options.document);
favoritesDrawer.dispose();
},
@@ -1783,29 +1791,42 @@ export function createMarketController(options: CreateMarketControllerOptions) {
};
}
function scheduleSync(): void {
function scheduleSync(): Promise<void> {
if (isDisposed) {
return;
return Promise.resolve();
}
if (isSyncRunning) {
if (activeSyncPromise) {
needsResync = true;
return;
return activeSyncPromise;
}
if (isSyncScheduled) {
return;
if (scheduledSyncPromise) {
return scheduledSyncPromise;
}
isSyncScheduled = true;
const nextScheduledSyncPromise = new Promise<void>((resolve, reject) => {
resolveScheduledSync = resolve;
rejectScheduledSync = reject;
});
scheduledSyncPromise = nextScheduledSyncPromise;
void nextScheduledSyncPromise.catch(() => undefined);
scheduledSyncTimeoutId = options.window.setTimeout(() => {
const resolve = resolveScheduledSync;
const reject = rejectScheduledSync;
scheduledSyncTimeoutId = null;
isSyncScheduled = false;
scheduledSyncPromise = null;
resolveScheduledSync = null;
rejectScheduledSync = null;
if (isDisposed) {
resolve?.();
return;
}
void runSyncCycle();
const syncPromise = runSyncCycle();
void syncPromise.catch(() => undefined);
void syncPromise.then(resolve, reject);
}, 0);
return nextScheduledSyncPromise;
}
function runWithoutMutationSync(callback: () => void): void {
@@ -1832,36 +1853,52 @@ export function createMarketController(options: CreateMarketControllerOptions) {
});
}
async function runSyncCycle(): Promise<void> {
function runSyncCycle(): Promise<void> {
if (isDisposed) {
return;
return Promise.resolve();
}
if (isSyncRunning) {
if (activeSyncPromise) {
needsResync = true;
return activeSyncPromise;
}
const syncPromise = runSingleSyncCycle();
activeSyncPromise = syncPromise;
void syncPromise.then(
() => {
completeSyncCycle(syncPromise);
},
() => {
completeSyncCycle(syncPromise);
}
);
return syncPromise;
}
function completeSyncCycle(syncPromise: Promise<void>): void {
if (activeSyncPromise !== syncPromise) {
return;
}
isSyncRunning = true;
try {
toolbar = ensurePluginToolbar(options.document, toolbarHandlers);
await hydrateCurrentPage();
if (needsFavoritesRefresh) {
needsFavoritesRefresh = false;
await refreshFavorites();
}
applyCurrentView();
lastKnownPageSignature = readMarketPageSignature(options.document);
} finally {
isSyncRunning = false;
if (isDisposed) {
return;
}
if (needsResync) {
needsResync = false;
scheduleSync();
}
activeSyncPromise = null;
if (isDisposed || !needsResync) {
return;
}
needsResync = false;
scheduleSync();
}
async function runSingleSyncCycle(): Promise<void> {
toolbar = ensurePluginToolbar(options.document, toolbarHandlers);
await hydrateCurrentPage();
if (needsFavoritesRefresh) {
needsFavoritesRefresh = false;
await refreshFavorites();
}
applyCurrentView();
lastKnownPageSignature = readMarketPageSignature(options.document);
}
}