ember-concurrency is the go to solution in the Ember community for tracking async action state and many other tasks around async behaviour.
ember-stateful-promise
seeks to simplify with native async/await
instead of generators and expose a few flags on a promise object for you to use. Moreover, they are tracked! This library can be used if you simply need derived state your async functions and/or need a lightweight version of ember-concurrency.
Also ember-promise-helpers is another great library if you want to calculate state from your promises. ember-stateful-promise
is different in that is seeks to provide derived state.
Lastly, if you already use ember-concurrency but rather author with async/await
, ember-concurrency-async is available as a babel build time plugin. Again, you just need to weigh the tradeoffs (size, complexity) for your project.
Supports
- Derived state
- Debouncing async functions
- Cleanup of async functions wired up with
@ember/destroyable
isRunning
isResolved
isError
isCanceled
performCount
cancel()
// this.clickMe.cancel()
There are a few ways to use this addon. Likely, you only need the stateful-function
decorator. However, if you need the lower level util, we make that available as StatefulPromise
as well.
import Component from '@glimmer/component';
import { action } from '@ember/object';
import { statefulFunction } from 'ember-stateful-promise/decorators/stateful-function';
class MyComponent extends Component {
@statefulFunction
async clickMe() {
await fetch(url);
}
}
Note - the default behaviour out of the box is to debounce
the action. When clicked while a promise is outstanding, the first promise will be rejected and a new promise will be created.
To throttle the function, pass { throttle: true }
to the decorator arguments.
import Component from '@glimmer/component';
import { action } from '@ember/object';
import { statefulFunction } from 'ember-stateful-promise/decorators/stateful-function';
class MyComponent extends Component {
@statefulFunction({ throttle: true })
async clickMe() {
await fetch(url);
}
}
@statefulFunction
replaces @action
while giving you all the features of this addon!
- Promise
interface
import { StatefulPromise } from 'ember-stateful-promise/utils/stateful-promise';
const promise = fetch(url);
let result = new StatefulPromise((resolveFn, rejectFn) => {
promise.then((data) => resolveFn(data)).catch((e) => rejectFn(e));
});
result.isRunning; // true
result.isResolved; // false
result.isError; // false
await result;
result.isRunning; // false
result.isResolved; // true
result.isError; // false
create
method with destroyable
import { StatefulPromise } from 'ember-stateful-promise/utils/stateful-promise';
const promise = fetch(url);
let result = new StatefulPromise().create(this, promise);
result.isRunning; // true
result.isResolved; // false
result.isError; // false
await result;
result.isRunning; // false
result.isResolved; // true
result.isError; // false
import { StatefulPromise } from 'ember-stateful-promise/utils/stateful-promise';
import { action } from '@ember/object';
class MyComponent extends Component {
@action
clickMe() {
const promise = fetch(url);
// Destroyable registered
let result = new StatefulPromise().create(this, (resolveFn, rejectFn) => {
promise.then((data) => resolveFn(data)).catch((e) => rejectFn(e));
});
// Component destroyed
// and then
try {
await result;
} catch (e) {
// WILL ERROR here!
}
}
}
- Ember.js v3.20 or above
- Ember CLI v3.20 or above
- Node.js v12 or above
ember install ember-stateful-promise
See the Contributing guide for details.
This project is licensed under the MIT License.