-
Notifications
You must be signed in to change notification settings - Fork 34
Open
Description
In typescript, a very common pattern is to share a promise in multiple places. For example:
class Foo {
data: Promise<number>;
constructor() {
this.data = (async () => 5)();
}
async getData() {
return await this.data;
}
}
const foo = new Foo();
console.log(await foo.getData());
However, this can't be done directly with Operation as they can only be computed once:
const func = function* () {
console.log("compute");
return 5;
}
const started = func();
console.log(await run(() => started)); // returns 5
console.log(await run(() => started)); // returns undefined
Solution
A solution to this is to use the same run
(aka the same Task
) multiple times instead of creating a new task every time
const func = function* () {
console.log("compute");
return 5;
}
const started = func();
const started2 = run(() => started) // save the `Task` to reuse it
console.log(await started2); // returns 5
console.log(await started2); // returns 5 again!
main(function* () {
// and this can even be used as a generator!
console.log(yield* started2); // still 5
console.log(yield* started2); // still 5
});
That is to say, I think Task
is the go-to when you want this kind of Promise-like behavior. The only caveat to this approach is that it doesn't work when you try to chain the result of the task as described in solution (3) in #944
Other options
I noticed that effect-ts
handles this differently by having a fork
and join
command: https://effect.website/docs/additional-resources/effect-vs-promise/#faq
iplaylf2
Metadata
Metadata
Assignees
Labels
No labels