mirror of
https://github.com/kmc7468/arkvault.git
synced 2026-02-04 08:06:56 +00:00
디렉터리 및 카테고리 페이지에서 탐색시의 깜빡임 현상 완화
This commit is contained in:
@@ -116,6 +116,6 @@ const storeToIndexedDB = (info: CategoryInfo) => {
|
||||
return { ...info, exists: true as const };
|
||||
};
|
||||
|
||||
export const getCategoryInfo = async (id: CategoryId, masterKey: CryptoKey) => {
|
||||
return await cache.get(id, masterKey);
|
||||
export const getCategoryInfo = (id: CategoryId, masterKey: CryptoKey) => {
|
||||
return cache.get(id, masterKey);
|
||||
};
|
||||
|
||||
@@ -97,6 +97,6 @@ const storeToIndexedDB = (info: DirectoryInfo) => {
|
||||
return { ...info, exists: true as const };
|
||||
};
|
||||
|
||||
export const getDirectoryInfo = async (id: DirectoryId, masterKey: CryptoKey) => {
|
||||
return await cache.get(id, masterKey);
|
||||
export const getDirectoryInfo = (id: DirectoryId, masterKey: CryptoKey) => {
|
||||
return cache.get(id, masterKey);
|
||||
};
|
||||
|
||||
@@ -168,10 +168,10 @@ const bulkStoreToIndexedDB = (infos: FileInfo[]) => {
|
||||
return infos.map((info) => [info.id, { ...info, exists: true }] as const);
|
||||
};
|
||||
|
||||
export const getFileInfo = async (id: number, masterKey: CryptoKey) => {
|
||||
return await cache.get(id, masterKey);
|
||||
export const getFileInfo = (id: number, masterKey: CryptoKey) => {
|
||||
return cache.get(id, masterKey);
|
||||
};
|
||||
|
||||
export const bulkGetFileInfo = async (ids: number[], masterKey: CryptoKey) => {
|
||||
return await cache.bulkGet(new Set(ids), masterKey);
|
||||
export const bulkGetFileInfo = (ids: number[], masterKey: CryptoKey) => {
|
||||
return cache.bulkGet(new Set(ids), masterKey);
|
||||
};
|
||||
|
||||
@@ -29,8 +29,6 @@ export class FilesystemCache<K, V extends object> {
|
||||
this.map.set(key, newState);
|
||||
}
|
||||
|
||||
state.promise = newPromise;
|
||||
|
||||
(state.value
|
||||
? Promise.resolve(state.value)
|
||||
: this.options.fetchFromIndexedDB(key).then((loadedInfo) => {
|
||||
@@ -54,7 +52,8 @@ export class FilesystemCache<K, V extends object> {
|
||||
state.promise = undefined;
|
||||
});
|
||||
|
||||
return newPromise;
|
||||
state.promise = newPromise;
|
||||
return state.value ?? newPromise;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -108,12 +107,17 @@ export class FilesystemCache<K, V extends object> {
|
||||
});
|
||||
});
|
||||
|
||||
return Promise.all(
|
||||
const bottleneckPromises = Array.from(
|
||||
keys
|
||||
.keys()
|
||||
.filter((key) => this.map.get(key)!.value === undefined)
|
||||
.map((key) => this.map.get(key)!.promise!),
|
||||
).then(() => new Map(keys.keys().map((key) => [key, this.map.get(key)!.value!] as const)));
|
||||
);
|
||||
const makeResult = () =>
|
||||
new Map(keys.keys().map((key) => [key, this.map.get(key)!.value!] as const));
|
||||
return bottleneckPromises.length > 0
|
||||
? Promise.all(bottleneckPromises).then(makeResult)
|
||||
: makeResult();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
93
src/lib/utils/HybridPromise.ts
Normal file
93
src/lib/utils/HybridPromise.ts
Normal file
@@ -0,0 +1,93 @@
|
||||
type MaybePromise<T> = T | Promise<T> | HybridPromise<T>;
|
||||
|
||||
type HybridPromiseState<T> =
|
||||
| { mode: "sync"; status: "fulfilled"; value: T }
|
||||
| { mode: "sync"; status: "rejected"; reason: unknown }
|
||||
| { mode: "async"; promise: Promise<T> };
|
||||
|
||||
export class HybridPromise<T> implements PromiseLike<T> {
|
||||
private isConsumed = false;
|
||||
|
||||
private constructor(private readonly state: HybridPromiseState<T>) {
|
||||
if (state.mode === "sync" && state.status === "rejected") {
|
||||
queueMicrotask(() => {
|
||||
if (!this.isConsumed) {
|
||||
throw state.reason;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
isSync(): boolean {
|
||||
return this.state.mode === "sync";
|
||||
}
|
||||
|
||||
toPromise(): Promise<T> {
|
||||
this.isConsumed = true;
|
||||
|
||||
if (this.state.mode === "async") return this.state.promise;
|
||||
return this.state.status === "fulfilled"
|
||||
? Promise.resolve(this.state.value)
|
||||
: Promise.reject(this.state.reason);
|
||||
}
|
||||
|
||||
static resolve<T>(value: MaybePromise<T>): HybridPromise<T> {
|
||||
if (value instanceof HybridPromise) return value;
|
||||
return new HybridPromise(
|
||||
value instanceof Promise
|
||||
? { mode: "async", promise: value }
|
||||
: { mode: "sync", status: "fulfilled", value },
|
||||
);
|
||||
}
|
||||
|
||||
static reject<T = never>(reason?: unknown): HybridPromise<T> {
|
||||
return new HybridPromise({ mode: "sync", status: "rejected", reason });
|
||||
}
|
||||
|
||||
then<TResult1 = T, TResult2 = never>(
|
||||
onfulfilled?: ((value: T) => MaybePromise<TResult1>) | null | undefined,
|
||||
onrejected?: ((reason: unknown) => MaybePromise<TResult2>) | null | undefined,
|
||||
): HybridPromise<TResult1 | TResult2> {
|
||||
this.isConsumed = true;
|
||||
|
||||
if (this.state.mode === "async") {
|
||||
return new HybridPromise({
|
||||
mode: "async",
|
||||
promise: this.state.promise.then(onfulfilled, onrejected) as any,
|
||||
});
|
||||
}
|
||||
|
||||
try {
|
||||
if (this.state.status === "fulfilled") {
|
||||
if (!onfulfilled) return HybridPromise.resolve(this.state.value as any);
|
||||
return HybridPromise.resolve(onfulfilled(this.state.value));
|
||||
} else {
|
||||
if (!onrejected) return HybridPromise.reject(this.state.reason);
|
||||
return HybridPromise.resolve(onrejected(this.state.reason));
|
||||
}
|
||||
} catch (e) {
|
||||
return HybridPromise.reject(e);
|
||||
}
|
||||
}
|
||||
|
||||
catch<TResult = never>(
|
||||
onrejected?: ((reason: unknown) => MaybePromise<TResult>) | null | undefined,
|
||||
): HybridPromise<T | TResult> {
|
||||
return this.then<T, TResult>(null, onrejected);
|
||||
}
|
||||
|
||||
finally(onfinally?: (() => void) | null | undefined): HybridPromise<T> {
|
||||
this.isConsumed = true;
|
||||
|
||||
if (this.state.mode === "async") {
|
||||
return new HybridPromise({ mode: "async", promise: this.state.promise.finally(onfinally) });
|
||||
}
|
||||
|
||||
try {
|
||||
onfinally?.();
|
||||
return new HybridPromise(this.state);
|
||||
} catch (e) {
|
||||
return HybridPromise.reject(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
export * from "./format";
|
||||
export * from "./gotoStateful";
|
||||
export * from "./HybridPromise";
|
||||
export * from "./sort";
|
||||
|
||||
Reference in New Issue
Block a user