UNPKG

ember-stateful-promise

Version:
173 lines (123 loc) 5.49 kB
ember-stateful-promise ============================================================================== [![Download count all time](https://img.shields.io/npm/dt/ember-stateful-promise.svg)](https://badge.fury.io/js/ember-stateful-promise) [![GitHub Actions Build Status](https://img.shields.io/github/workflow/status/snewcomer/ember-stateful-promise/CI/main)](https://github.com/snewcomer/ember-stateful-promise/actions/workflows/ci.yml?query=branch%3Amain) [![npm version](https://badge.fury.io/js/ember-stateful-promise.svg)](https://badge.fury.io/js/ember-stateful-promise) [![Ember Observer Score](https://emberobserver.com/badges/ember-stateful-promise.svg)](https://emberobserver.com/addons/ember-stateful-promise) [ember-concurrency](http://ember-concurrency.com/docs/introduction/) 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](https://github.com/fivetanley/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](https://github.com/chancancode/ember-concurrency-async) is available as a babel build time plugin. Again, you just need to weigh the tradeoffs (size, complexity) for your project. ## API Supports 1. Derived state 2. Debouncing async functions 3. Cleanup of async functions wired up with `@ember/destroyable` - `isRunning` - `isResolved` - `isError` - `isCanceled` - `performCount` - `cancel()` // this.clickMe.cancel() ## Usage 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. ### Decorator ```js 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); } } ``` ```hbs <button disabled={{if this.clickMe.isRunning "true"}} {{on "click" this.clickMe}}> Click </button> <p>(Clicked this many times - {{this.clickMe.performCount}})</p> ``` 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. ```js 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! ### Stateful Promise - Promise `interface` ```js 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 ```js 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 ``` ```js 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! } } } ``` Compatibility ------------------------------------------------------------------------------ * Ember.js v3.20 or above * Ember CLI v3.20 or above * Node.js v12 or above Installation ------------------------------------------------------------------------------ ``` ember install ember-stateful-promise ``` Contributing ------------------------------------------------------------------------------ See the [Contributing](CONTRIBUTING.md) guide for details. License ------------------------------------------------------------------------------ This project is licensed under the [MIT License](LICENSE.md).