Skip to content

Commit

Permalink
Remove setters from signalFunction()'s State
Browse files Browse the repository at this point in the history
  • Loading branch information
justinfagnani committed Jul 4, 2024
1 parent 85d754a commit 9fdc17e
Showing 1 changed file with 14 additions and 21 deletions.
35 changes: 14 additions & 21 deletions src/async-function.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,23 +24,18 @@ export function signalFunction<Return>(fn: () => Return): State<Return> {
* State container that represents the asynchrony of a `signalFunction`
*/
export class State<Value> {

#data = new Signal.State<SignalAsyncData<Value> | null>(null);
#promise = new Signal.State<Value | undefined>(undefined);

get data() {
this.#computed.get();
return this.#data.get();
}
set data(value) {
this.#data.set(value);
}

#promise = new Signal.State<Value | undefined>(undefined);
get promise() {
this.#computed.get();
return this.#promise.get();
}
set promise(value) {
this.#promise.set(value);
}

/**
* ember-async-data doesn't catch errors,
Expand All @@ -54,9 +49,6 @@ export class State<Value> {
this.#computed.get();
return this.#caughtError.get();
}
set caughtError(value) {
this.#caughtError.set(value);
}

#fn: () => Value;

Expand Down Expand Up @@ -192,29 +184,30 @@ export class State<Value> {
* `error` or `resolvedValue` will remain as they were previously
* until this promise resolves, and then they'll be updated to the new values.
*/
retry = async () => {
async retry() {
try {
/**
* This function has two places where it can error:
* - immediately when inovking `fn` (where auto-tracking occurs)
* - after an await, "eventually"
*/
await this._dangerousRetry();
await this.#dangerousRetry();
} catch (e) {
this.caughtError = e;
this.#caughtError.set(e);
}
};

_dangerousRetry = async () => {
async #dangerousRetry() {
// We've previously had data, but we're about to run-again.
// we need to do this again so `isLoading` goes back to `true` when re-running.
// NOTE: we want to do this _even_ if this.data is already null.
// it's all in the same tracking frame and the important thing is taht
// it's all in the same tracking frame and the important thing is that
// we can't *read* data here.
this.data = null;
this.#data.set(null);

// We need to invoke this before going async so that tracked properties are consumed (entangled with) synchronously
this.promise = this.#fn();
// We need to invoke this before going async so that tracked properties are
// consumed (entangled with) synchronously
this.#promise.set(this.#fn());

// TrackedAsyncData interacts with tracked data during instantiation.
// We don't want this internal state to entangle with `signalFunction`
Expand All @@ -226,8 +219,8 @@ export class State<Value> {
* This is detached from the tracking frame (via the above await),
* se the UI can update accordingly, without causing us to refetch
*/
this.caughtError = null;
this.data = new SignalAsyncData(this.promise);
this.#caughtError.set(null);
this.#data.set(new SignalAsyncData<Value>(this.promise!));

return this.promise;
};
Expand Down

0 comments on commit 9fdc17e

Please sign in to comment.