Skip to content

Commit

Permalink
feat(trackedFunction): second attempt at implementing a re-callable t…
Browse files Browse the repository at this point in the history
…rackedFunction but this time with weird magic
  • Loading branch information
velrest committed Jul 12, 2022
1 parent d5d6b05 commit 066fb9a
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 51 deletions.
113 changes: 63 additions & 50 deletions ember-resources/src/util/function.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,74 +95,87 @@ export function trackedFunction<Return>(...passedArgs: UseFunctionArgs<Return>)
return buildResource(context, fn, initialValue);
}

function createPropertyValue(getValue) {
const propertyValue = function () {
propertyValue.state = getValue();
return propertyValue.state;
};

Object.defineProperty(propertyValue, "value", {
get: function () {
return (
propertyValue.state.resolvedValue ||
propertyValue.state.initialValue ||
null
);
},
});
Object.defineProperty(propertyValue, "isPending", {
get: function () {
return !propertyValue.state.isResolved;
},
});
Object.defineProperty(propertyValue, "isLoading", {
get: function () {
return propertyValue.state.isPending;
},
});
Object.defineProperty(propertyValue, "isError", {
get: function () {
return Boolean(propertyValue.state.error);
},
});

return propertyValue;
}

function buildResource<Return>(
context: any,
fn: ResourceFn<Return>,
initialValue: Return | undefined
) {
const getValue = async (state) => {
try {
console.log("Reexecuted");

let notQuiteValue = fn(hooks);
let promise = Promise.resolve(notQuiteValue);

waitForPromise(promise);

let result = await promise;

state.error = undefined;
state.resolvedValue = result;
} catch (e) {
state.error = e;
} finally {
state.isResolved = true;
}
};

return resource<State<Return>>(context, (hooks) => {
let state = new State(initialValue);
state.fn = fn;
state.context = context;
(async () => {
try {
console.log("Reexecuted");

let notQuiteValue = fn(hooks);
let promise = Promise.resolve(notQuiteValue);

waitForPromise(promise);

let result = await promise;

state.error = undefined;
state.resolvedValue = result;
} catch (e) {
state.error = e;
} finally {
state.isResolved = true;
}
})();

return state;
});
}
const state = new State(initialValue);
getValue(state);

export function executeTrackedFunction<Value>(oldState: State<Value>) {
assert(`Expected State to have property "fn"`, oldState.fn !== undefined);
const context = oldState.context;
const fn: ResourceFn<Value> = oldState.fn;
const initialValue = oldState.initialValue;
return buildResource(context, fn, initialValue);
const propertyValue = createPropertyValue(() =>
getValue(new State(initialValue))
);
propertyValue.state = tracked(state);

return propertyValue;
});
}

/**
* State container that represents the asynchrony of a `trackedFunction`
*/
export class State<Value> {
@tracked isResolved = false;
@tracked fn?: ResourceFn<Value>;
@tracked context?: any;
@tracked resolvedValue?: Value;
@tracked error?: unknown;

constructor(public initialValue?: Value) {}

get value() {
return this.resolvedValue || this.initialValue || null;
}

get isPending() {
return !this.isResolved;
}

get isLoading() {
return this.isPending;
}

get isError() {
return Boolean(this.error);
}
}

/**
Expand Down
3 changes: 2 additions & 1 deletion testing/ember-app/app/components/util/function.gts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ export default class GlintTest extends Component {
}

executeTracked(){
this.aMap = executeTrackedFunction(this.aMap)
const value = this.aMap()
console.log this.aMap.value
}


Expand Down

0 comments on commit 066fb9a

Please sign in to comment.