You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@async-library/core will contain all the core functionality that Async Library provides. It will generally not be used directly, but be a dependency of @async-library/react-async-hook for example. It should have feature parity with react-async and react-async-hook (outside of React specifics).
This description is updated as the discussion unfolds.
Features
Standardized API (both in and out)
Full state management for a single instance in local state
No global store (otherwise you might as well use Redux Saga)
Cancellation (with AbortController)
DevTools integration (e.g. allow replaying a promiseFn)
To discuss:
Should we use generators instead of promises?
Should we use an internal state machine?
Should we allow users to create their own async state machine?
Core API
States:
initial nothing happened yet (or reinitialize was invoked)
pending promise is loading or paused
fulfilled promise was fulfilled with data
rejected promise was rejected with error
Config options:
fn async function that will be invoked on run
runOnInit flag to enable running on init (mount) [do we really need this?]
initialValue initialize value to a predefined value or error [should this be separate values for data and error?]
Callback options:
onInit when first initialized (i.e. mount)
onData when promise has fulfilled with data
onError when promise has rejected with error
onAbort when promise has aborted
onDestroy when destroying the instance (i.e. unmount)
Actions:
run invoke fn
abort cancel a pending promise and invoke AbortController::abort
reinitialize abort and reset state to initial
Metadata:
runCount number of times run was invoked (automatically or manually)
startedAt when the last run was invoked
finishedAt when the last promise was fulfilled or rejected
This API deviates quite a bit from React Async. Notably:
promiseFn and deferFn are combined into fn
promise is dropped as an option. You can just pass () => promise instead.
What exactly are you targeting here? Internal API? External API? Saga-like effect yields with return values? Just flow control?
Just out of my head:
I would oppose generators for an outside API - not many people know how to use generators well and it might intimidate many users.
Generators for flow control internally are great
Generators where values are injected into the running generator by calling next break type safety. TS3.6 gives a little more security, but things like this can still not be properly inferred:
function*correct(){constpromise=Promise.resolve(3);constresult: number=yieldpromise;}function*problematic(){constpromise=Promise.resolve(3);constresult: string=yieldpromise;// this is wrong and cannot be checked by TS}
So I'm not a big fan for generators that yield/inject more than exactly one fixed type (as that is possible with TS).
As for the point that currently, promises might leak memory and lead to uncaught promise rejections, we could cicumvent that:
all promises, even if cancelled are always resolved
instead of rejecting a cancelled promise, the resolving values contains a status indicator.
So those promises (that would in the case of async-library/react-async#92 (comment) ) cause an uncaught error. Would just either resolve to { status: "resolved", value: "..." } or {status: "cancelled", reason: "..." }
Not really, but a generator would make for a weird subscription, too. You'd have too loop over the Iterable or call next() manually. I'd rather use a callback for that.
Activity
phryneas commentedon Sep 8, 2019
What exactly are you targeting here? Internal API? External API? Saga-like effect yields with return values? Just flow control?
Just out of my head:
nextbreak type safety. TS3.6 gives a little more security, but things like this can still not be properly inferred:So I'm not a big fan for generators that yield/inject more than exactly one fixed type (as that is possible with TS).
As for the point that currently, promises might leak memory and lead to uncaught promise rejections, we could cicumvent that:
So those promises (that would in the case of async-library/react-async#92 (comment) ) cause an uncaught error. Would just either resolve to
{ status: "resolved", value: "..." }or{status: "cancelled", reason: "..." }ghengeveld commentedon Sep 8, 2019
Agreed, I have a preference for promises over generators as well. However, will it allow us to implement subscriptions?
I've updated the issue to add a draft of the core API. It's by no means complete.
phryneas commentedon Sep 8, 2019
Not really, but a generator would make for a weird subscription, too. You'd have too loop over the Iterable or call next() manually. I'd rather use a callback for that.