Skip to content

Commit cabf9c2

Browse files
committed
Remaining promise API
1 parent dbbdc44 commit cabf9c2

File tree

7 files changed

+68
-40
lines changed

7 files changed

+68
-40
lines changed

datacore.api.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,7 @@ export class Datacore extends Component {
344344
//
345345
// @internal
346346
importer: FileImporter;
347-
index(): void;
347+
index(): Promise<void>;
348348
initialize(): void;
349349
initialized: boolean;
350350
// Warning: (ae-forgotten-export) The symbol "DatacoreInitializer" needs to be exported by the entry point index.d.ts

src/api/ui/embed.tsx

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -164,14 +164,14 @@ export function useLineSpan(path: string, start: number, end: number): LineSpanC
164164
}
165165

166166
// Try to load the file asynchronously.
167-
datacore
168-
.read(file)
169-
.then((content) => {
167+
(async () => {
168+
try {
169+
const content = await datacore.read(file);
170170
update({ type: "loaded", content: lineRange(content, start, end) });
171-
})
172-
.catch((error) => {
173-
update({ type: "error", message: error.message });
174-
});
171+
} catch (error) {
172+
update({ type: "error", message: error instanceof Error ? error.message : String(error) });
173+
}
174+
})();
175175
}, [path, start, end]);
176176

177177
return state;

src/index/datacore.ts

Lines changed: 30 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -110,30 +110,30 @@ export class Datacore extends Component {
110110
this.index();
111111
}
112112

113-
/** Starts the background initializer. */
114-
index() {
113+
/** Indexes all documents in the vault. Wait on this if you want to wait for the whole index to be ready. */
114+
async index() {
115115
// Asynchronously initialize actual content in the background using a lifecycle-respecting object.
116116
const init = (this.initializer = new DatacoreInitializer(this));
117-
init.finished().then((stats) => {
118-
this.initialized = true;
119-
this.initializer = undefined;
120-
this.removeChild(init);
117+
this.addChild(init);
121118

122-
this.datastore.touch();
123-
this.trigger("update", this.revision);
124-
this.trigger("initialized");
119+
await init.finished();
125120

126-
// Clean up any documents which no longer exist in the vault.
127-
// TODO: I think this may race with other concurrent operations, so
128-
// this may need to happen at the start of init and not at the end.
129-
const currentFiles = this.vault.getFiles().map((file) => file.path);
130-
this.persister.synchronize(currentFiles);
131-
});
121+
this.initialized = true;
122+
this.initializer = undefined;
123+
this.removeChild(init);
132124

133-
this.addChild(init);
125+
this.datastore.touch();
126+
this.trigger("update", this.revision);
127+
this.trigger("initialized");
128+
129+
// Clean up any documents which no longer exist in the vault.
130+
// TODO: I think this may race with other concurrent operations, so
131+
// this may need to happen at the start of init and not at the end.
132+
const currentFiles = this.vault.getFiles().map((file) => file.path);
133+
this.persister.synchronize(currentFiles);
134134
}
135135

136-
private rename(file: TAbstractFile, oldPath: string) {
136+
private async rename(file: TAbstractFile, oldPath: string) {
137137
if (!(file instanceof TFile)) {
138138
return;
139139
}
@@ -142,7 +142,9 @@ export class Datacore extends Component {
142142
// This is less optimal than what can probably be done, but paths are used in a bunch of places
143143
// (for sections, tasks, etc to refer to their parent file) and it requires some finesse to fix.
144144
this.datastore.delete(oldPath);
145-
this.reload(file).then(() => this.trigger("rename", file.path, oldPath));
145+
await this.reload(file);
146+
147+
this.trigger("rename", file.path, oldPath);
146148

147149
// TODO: For correctness, probably have to either fix links in all linked files OR
148150
// just stop normalizing links in the store. We can traverse the links index to do so
@@ -364,9 +366,16 @@ export class DatacoreInitializer extends Component {
364366
const next = this.queue.pop();
365367
if (next) {
366368
this.current.push(next);
367-
this.init(next)
368-
.then((result) => this.handleResult(next, result))
369-
.catch((result) => this.handleResult(next, result));
369+
370+
// Run asynchronously to allow for concurrency.
371+
(async () => {
372+
try {
373+
const result = await this.init(next);
374+
this.handleResult(next, result);
375+
} catch (error) {
376+
this.handleResult(next, { status: "skipped" });
377+
}
378+
})();
370379

371380
this.runNext();
372381
} else if (!next && this.current.length == 0) {

src/index/embed-queue.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,18 @@ export class EmbedQueue extends Component {
4444
const read = this.vault.cachedRead(file);
4545
this.active.set(file.path, read);
4646

47-
read.then((content) => this.finish(file, Result.success(content))).catch((error) =>
48-
this.finish(file, Result.failure(error))
49-
);
47+
// This function is non-blocking and will await on the read promise in the background.
48+
this.run(file, read);
49+
}
50+
}
51+
52+
/** Wait on the read promise and then finish the load, catching errors. */
53+
private async run(file: TFile, data: Promise<string>) {
54+
try {
55+
const content = await data;
56+
this.finish(file, Result.success(content));
57+
} catch (error) {
58+
this.finish(file, Result.failure(error));
5059
}
5160
}
5261

src/index/persister.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,8 @@ export class LocalStorageCache {
3535

3636
/** Load file metadata by path. */
3737
public async loadFile(path: string): Promise<Cached<Partial<unknown>> | null | undefined> {
38-
return this.persister.getItem(this.fileKey(path)).then((raw) => {
39-
return raw as unknown as Cached<Partial<unknown>>;
40-
});
38+
const raw = await this.persister.getItem(this.fileKey(path));
39+
return raw as unknown as Cached<Partial<unknown>>;
4140
}
4241

4342
/** Store file metadata by path. */

src/ui/loading-boundary.tsx

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,15 @@ export function ScriptContainer({
6464
setElement(undefined);
6565
setError(undefined);
6666

67-
executor()
68-
.then((result) => setElement(makeRenderableElement(result, sourcePath)))
69-
.catch((error) => setError(error));
67+
// TODO: Avoid multiple concurrent executions of the same script.
68+
(async () => {
69+
try {
70+
const result = await executor();
71+
setElement(makeRenderableElement(result, sourcePath));
72+
} catch (error) {
73+
setError(error instanceof Error ? error : new Error(String(error)));
74+
}
75+
})();
7076
}, [executor, sourcePath]);
7177

7278
// Propogate error upwards.

src/ui/markdown.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,12 @@ function RawMarkdown({
109109
if (!container.current) return;
110110

111111
container.current.replaceChildren(...[]);
112-
MarkdownRenderer.render(app, content, container.current, sourcePath, component).then(() => {
112+
113+
(async () => {
114+
if (!container.current || !inline) return;
115+
await MarkdownRenderer.render(app, content, container.current, sourcePath, component);
116+
117+
// Have to check twice since the container might disappear during the async call.
113118
if (!container.current || !inline) return;
114119

115120
// Unwrap any created paragraph elements if we are inline.
@@ -137,7 +142,7 @@ function RawMarkdown({
137142
embed.addClass("is-loaded");
138143
embed = container.current.querySelector("span.internal-embed:not(.is-loaded)");
139144
}
140-
});
145+
})();
141146
}, [content, sourcePath, inline, container.current]);
142147

143148
return (

0 commit comments

Comments
 (0)