We can use getPromiseState
to dynamically load and render a component
import { getPromiseState } from 'reactiveweb/get-promise-state';
let state = getPromiseState(() => import('./some-module/component'));
<template>
{{#if state.isLoading}}
... pending ...
{{else if state.error}}
oh no!
{{else if state.resolved}}
<state.resolved />
{{/if}}
</template>
getPromiseState
can also be used in a class without @cached
, because it maintains its own cache.
import Component from '@glimmer/component';
import { getPromiseState } from 'reactiveweb/get-promise-state';
async function readFromSomewhere() { // implementation omitted for brevity
}
export default class Demo extends Component {
// doesn't matter how many times state is accessed, you get a stable state
get state() {
return getPromiseState(readFromSomewhere);
}
<template>
{{#if this.state.resolved}}
...
{{/if}}
</template>
}
A reactively constructed function will also be used and have its result cached between uses
import Component from '@glimmer/component';
import { getPromiseState } from 'reactiveweb/get-promise-state';
async function readFromSomewhere() { // implementation omitted for brevity
}
export default class Demo extends Component {
// Note: the @cached is important here because we don't want repeat accesses
// to cause doAsync to be called again unless @id changes
@cached
get promise() {
return this.doAsync(this.args.id);
}
get state() {
return getPromiseState(this.promise);
}
<template>
{{#if this.state.resolved}}
...
{{/if}}
</template>
}
NOTE: This getPromiseState
is not a replacement for WarpDrive's getRequestState
namely, the getPromiseState
in this library (reactiveweb) does not support futures, cancellation, or anything else specific to warp-drive.
comparison of pure capability
. | reactiveweb | @warpdrive/ember |
---|---|---|
use in module state[1] | ✅ | ✅ |
use in a getter[2] | ✅ | ✅ |
usable in template | ✅ | ✅ |
immediate has resolved value for resolved promise | ✅ | ✅ |
test waiter integration | ✅ | ✅ |
allows non-promises (forgiving inputs) | ✅ | ❌ |
can be used without build | ✅ | ❌[3] |
allows prepopulation of result cache by 3rd party | ❌ | ✅ |
discriminated states (helpful for TS) | ❌[4] | ✅ |
align with allSettled's return value | ❌[4:1] | ✅ |
All in all, they are very similar. The primary use case I had for creating my own is that I wanted dynamic module loading (with import) to be one line (shown in the first example).
reactiveweb's getPromiseState
is made primarily for my needs in my own projects, and I don't intend to say anything negative about @warp-drive
s getPromiseState
-- I actually took a lot of code from it! it's a good tool.
These projects of slightly different goals, so some additional information:
from the perspective of reactiveweb's set of goals:
. | reactiveweb | @warpdrive/ember |
---|---|---|
invokes a passed function automatically | ✅ | ❌ |
simple state return[5] | ⚠️[4:2] | ⚠️ [6] |
from the perspective of @warp-drive/core's set of goals
. | reactiveweb | @warpdrive/core |
---|---|---|
has a simple API surface | ❌ [7] | ✅ |
no dependencies | ❌ [8] | ⚠️[9] |
getPromiseState(promise);
↩︎
requires a stable reference to a promise. getter itself does not need to be cached. ↩︎
the warp-drive team is interested in this work, and wants to make REPLs and CDNs easier as well ↩︎
This is fixable, and probably with little effort, just needs doing ↩︎ ↩︎ ↩︎
in reactiveweb: State, and then in @warp-drive/*
: the PromiseState
is made of 3 sub types: PendingPromise, ResolvedPromise, and RejectedPromise. Over time, these will align slightly with allSettled's return value. ↩︎
has pending deprecations, otherwise ✅ ↩︎
@warp-drive/core
strives for API simplicity, which means few (if any) overloads on its utilities. ↩︎
reactiveweb (as a whole) does depend on on ember-resources, but ember-resources itself has no dependencies (for real), and is a very tiny use of a helper manager. Additionally, getPromiseState
does not depend on ember-resources
. ↩︎
Does not directly depend on any dependencies, but requires an integration into reactivity (which is technically true for reactiveweb
as well) ↩︎
Returns a reactive state for a given value, function, promise, or function that returns a promise.
Also caches the result for the given value, so
getPromiseState
will become synchronous if the passed value has already been resolved.Normally when trying to derive async state, you'll first need to invoke a function to get the promise from that function's return value. With
getPromiseState
, a passed function will be invoked for you, so you can skip that step.