chore: tweak resource implementation

pull/17123/head
Rich Harris 2 weeks ago
parent 0ff96567a3
commit bfd9e8f001

@ -19,12 +19,12 @@ export function resource(fn) {
/** /**
* @template T * @template T
* @implements {Partial<Promise<Awaited<T>>>} * @implements {Partial<Promise<T>>}
*/ */
class Resource { class Resource {
#init = false; #init = false;
/** @type {() => T} */ /** @type {() => T | Promise<T>} */
#fn; #fn;
/** @type {Source<boolean>} */ /** @type {Source<boolean>} */
@ -36,13 +36,13 @@ class Resource {
/** @type {Source<boolean>} */ /** @type {Source<boolean>} */
#ready = state(false); #ready = state(false);
/** @type {Source<Awaited<T> | undefined>} */ /** @type {Source<T | undefined>} */
#raw = state(undefined); #raw = state(undefined);
/** @type {Source<Promise<any>>} */ /** @type {Source<Promise<T>>} */
#promise; #promise;
/** @type {Derived<Awaited<T> | undefined>} */ /** @type {Derived<T | undefined>} */
#current = derived(() => { #current = derived(() => {
if (!get(this.#ready)) return undefined; if (!get(this.#ready)) return undefined;
return get(this.#raw); return get(this.#raw);
@ -51,27 +51,10 @@ class Resource {
/** {@type Source<any>} */ /** {@type Source<any>} */
#error = state(undefined); #error = state(undefined);
/** @type {Derived<Promise<Awaited<T>>['then']>} */ /** @type {Derived<Promise<T>['then']>} */
// @ts-expect-error - I feel this might actually be incorrect but I can't prove it yet.
// we are technically not returning a promise that resolves to the correct type... but it _is_ a promise that resolves at the correct time
#then = derived(() => { #then = derived(() => {
const p = get(this.#promise); const p = get(this.#promise);
return (resolve, reject) => p.then(resolve, reject);
return async (resolve, reject) => {
const result = /** @type {Promise<Awaited<T>>} */ (
(async () => {
await p;
await tick();
return get(this.#current);
})()
);
if (resolve || reject) {
return result.then(resolve, reject);
}
return result;
};
}); });
/** /**
@ -92,6 +75,7 @@ class Resource {
this.#init = true; this.#init = true;
} }
/** @type {ReturnType<typeof deferred<T>>} */
const { resolve, reject, promise } = deferred(); const { resolve, reject, promise } = deferred();
this.#latest.push(resolve); this.#latest.push(resolve);
@ -108,7 +92,7 @@ class Resource {
set(this.#raw, value); set(this.#raw, value);
set(this.#error, undefined); set(this.#error, undefined);
resolve(undefined); resolve(value);
}) })
.catch((e) => { .catch((e) => {
const idx = this.#latest.indexOf(resolve); const idx = this.#latest.indexOf(resolve);
@ -173,13 +157,13 @@ class Resource {
}; };
/** /**
* @param {Awaited<T>} value * @param {T} value
*/ */
set = (value) => { set = (value) => {
set(this.#ready, true); set(this.#ready, true);
set(this.#loading, false); set(this.#loading, false);
set(this.#error, undefined); set(this.#error, undefined);
set(this.#raw, value); set(this.#raw, value);
set(this.#promise, Promise.resolve()); set(this.#promise, Promise.resolve(value));
}; };
} }

Loading…
Cancel
Save