perf(core): load all pages after 10s (#4834)

This commit is contained in:
Peng Xiao
2023-11-03 17:42:29 +08:00
committed by GitHub
parent 61dc4a56f9
commit 7e381e830a
7 changed files with 102 additions and 15 deletions

View File

@@ -1,9 +1,13 @@
import { DebugLogger } from '@affine/debug';
import { assertExists, DisposableGroup } from '@blocksuite/global/utils';
import type { Page, Workspace } from '@blocksuite/store';
import type { Atom } from 'jotai';
import { atom, useAtomValue } from 'jotai';
import PQueue from 'p-queue';
import { useEffect } from 'react';
const logger = new DebugLogger('use-block-suite-workspace-page');
const weakMap = new WeakMap<Workspace, Map<string, Atom<Page | null>>>();
const emptyAtom = atom<Page | null>(null);
@@ -45,6 +49,52 @@ function getAtom(w: Workspace, pageId: string | null): Atom<Page | null> {
return map.get(pageId) as Atom<Page | null>;
}
}
// concurrently load 3 pages at most
const CONCURRENT_JOBS = 3;
const loadPageQueue = new PQueue({
concurrency: CONCURRENT_JOBS,
});
const loadedPages = new WeakSet<Page>();
const awaitForIdle = () =>
new Promise(resolve =>
requestIdleCallback(resolve, {
timeout: 1000, // do not wait for too long
})
);
const awaitForTimeout = (timeout: number) =>
new Promise(resolve => setTimeout(resolve, timeout));
/**
* Load a page and wait for it to be loaded
* This page will be loaded in a queue so that it will not jam the network and browser CPU
*/
export function loadPage(page: Page, priority = 0) {
if (loadedPages.has(page)) {
return Promise.resolve();
}
loadedPages.add(page);
return loadPageQueue.add(
async () => {
if (!page.loaded) {
await awaitForIdle();
await page.waitForLoaded();
// we do not know how long it takes to load a page here
// so that we just use 300ms timeout as the default page processing time
await awaitForTimeout(300);
logger.debug('page loaded', page.id);
} else {
// do nothing if it is already loaded
}
},
{
priority,
}
);
}
export function useBlockSuiteWorkspacePage(
blockSuiteWorkspace: Workspace,
@@ -55,8 +105,10 @@ export function useBlockSuiteWorkspacePage(
const page = useAtomValue(pageAtom);
useEffect(() => {
if (!page?.loaded) {
page?.waitForLoaded().catch(console.error);
if (page && !page.loaded) {
loadPage(page).catch(err => {
logger.error('Failed to load page', err);
});
}
}, [page]);