diff --git a/packages/automerge-repo/src/Repo.ts b/packages/automerge-repo/src/Repo.ts index 13a4c91d6..856dfdf85 100644 --- a/packages/automerge-repo/src/Repo.ts +++ b/packages/automerge-repo/src/Repo.ts @@ -420,6 +420,7 @@ export class Repo extends EventEmitter { options: AbortOptions = {} ): FindProgress { const { signal } = options + const abortPromise = abortable(signal) const documentId = interpretAsDocumentId(id) // Check cache first - return plain FindStep for terminal states @@ -451,22 +452,27 @@ export class Repo extends EventEmitter { const handle = that.#getHandle({ documentId }) yield { state: "loading", progress: 25, handle } - const loadedDoc = await (that.storageSubsystem + const loadingPromise = await (that.storageSubsystem ? that.storageSubsystem.loadDoc(handle.documentId) : Promise.resolve(null)) + const loadedDoc = await Promise.race([loadingPromise, abortPromise]) + if (loadedDoc) { handle.update(() => loadedDoc as Automerge.Doc) handle.doneLoading() yield { state: "loading", progress: 50, handle } } else { - await that.networkSubsystem.whenReady() + await Promise.race([that.networkSubsystem.whenReady(), abortPromise]) handle.request() yield { state: "loading", progress: 75, handle } } that.#registerHandleWithSubsystems(handle) - await handle.whenReady([READY, UNAVAILABLE, DELETED]) + await Promise.race([ + handle.whenReady([READY, UNAVAILABLE, DELETED]), + abortPromise, + ]) if (handle.state === UNAVAILABLE) { throw new Error(`Document ${id} is unavailable`) diff --git a/packages/automerge-repo/test/Repo.test.ts b/packages/automerge-repo/test/Repo.test.ts index a3051433d..ca2722003 100644 --- a/packages/automerge-repo/test/Repo.test.ts +++ b/packages/automerge-repo/test/Repo.test.ts @@ -1459,13 +1459,12 @@ describe("Repo.find() abort behavior", () => { it("can abort while waiting for ready state", async () => { // Create a repo with no network adapters so document can't become ready const repo = new Repo() - const handle = repo.create() - const url = handle.url + const url = generateAutomergeUrl() const controller = new AbortController() // Start find and abort after a moment - const findPromise = repo.find(handle.url, { signal: controller.signal }) + const findPromise = repo.find(url, { signal: controller.signal }) controller.abort() await expect(findPromise).rejects.toThrow("Operation aborted")