Members
(constant) all
A cancelation-aware variant of Promise.all.
The normal version of a Promise.all
just returns a regular, uncancelable
Promise. The ember-concurrency
variant of all()
has the following
additional behavior:
- if the task that
yield
edall()
is canceled, any of theTaskInstance
s passed in toall
will be canceled - if any of the
TaskInstance
s (or regular promises) passed in reject (or are canceled), all of the other unfinishedTaskInstance
s will be automatically canceled.
- Source:
(constant) allSettled
A cancelation-aware variant of RSVP.allSettled.
The normal version of a RSVP.allSettled
just returns a regular, uncancelable
Promise. The ember-concurrency
variant of allSettled()
has the following
additional behavior:
- if the task that
yield
edallSettled()
is canceled, any of theTaskInstance
s passed in toallSettled
will be canceled
- Source:
(constant) forever
Yielding forever
will pause a task indefinitely until
it is cancelled (i.e. via host object destruction, the restartable modifier,
or manual cancellation).
This is often useful in cases involving animation: if you're
using Liquid Fire, or some other animation scheme, sometimes you'll
notice buttons visibly reverting to their inactive states during
a route transition. By yielding forever
in a Component task that drives a
button's active state, you can keep a task indefinitely running
until the animation runs to completion.
NOTE: Liquid Fire also includes a useful waitUntilIdle()
method
on the liquid-fire-transitions
service that you can use in a lot
of these cases, but it won't cover cases of asynchrony that are
unrelated to animation, in which case forever
might be better suited
to your needs.
import { task, forever } from 'ember-concurrency';
export default class MyComponent extends Component {
@service myService;
@task *myTask() {
yield this.myService.doSomethingThatCausesATransition();
yield forever;
}
}
- Source:
(constant) hash
A cancelation-aware variant of RSVP.hash.
The normal version of a RSVP.hash
just returns a regular, uncancelable
Promise. The ember-concurrency
variant of hash()
has the following
additional behavior:
- if the task that
yield
edhash()
is canceled, any of theTaskInstance
s passed in tohash
will be canceled - if any of the items rejects/cancels, all other cancelable items
(e.g.
TaskInstance
s) will be canceled
- Source:
(constant) hashSettled
A cancelation-aware variant of RSVP.hashSettled.
The normal version of a RSVP.hashSettled
just returns a regular, uncancelable
Promise. The ember-concurrency
variant of hashSettled()
has the following
additional behavior:
- if the task that
yield
edhashSettled()
is canceled, any of theTaskInstance
s passed in tohashSettled
will be canceled
- Source:
(constant) race
A cancelation-aware variant of Promise.race.
The normal version of a Promise.race
just returns a regular, uncancelable
Promise. The ember-concurrency
variant of race()
has the following
additional behavior:
- if the task that
yield
edrace()
is canceled, any of theTaskInstance
s passed in torace
will be canceled - once any of the tasks/promises passed in complete (either success, failure,
or cancelation), any of the
TaskInstance
s passed in will be canceled
- Source:
Methods
animationFrame()
Yielding animationFrame()
will pause a task until after the next animation
frame using the native requestAnimationFrame()
browser API.
The task below, when performed, will print the time since the last loop run for every animation frame.
export default class MyComponent extends Component {
@task *myTask() {
let lastNow = performance.now();
while (true) {
yield animationFrame();
let now = performance.now();
let dt = now - lastNow;
lastNow = now;
console.log(dt);
}
}
}
- Source:
didCancel(error) → {boolean}
Returns true if the object passed to it is a TaskCancelation error.
If you call someTask.perform().catch(...)
or otherwise treat
a TaskInstance
like a promise, you may need to
handle the cancelation of a TaskInstance differently from
other kinds of errors it might throw, and you can use this
convenience function to distinguish cancelation from errors.
click() {
this.myTask.perform().catch(e => {
if (!didCancel(e)) { throw e; }
});
}
Parameters:
Name | Type | Description |
---|---|---|
error |
object | the caught error, which might be a TaskCancelation |
Returns:
- Type
- boolean
dropTask(optionsopt, nullable) → {Task}
Turns the decorated generator function into a task and applies the
drop
modifier.
Optionally takes a hash of options that will be applied as modifiers to the
task. For instance maxConcurrency
, on
, or group
.
You can also define an
Encapsulated Task
by decorating an object that defines a perform
generator
method.
import Component from '@ember/component';
import { task, dropTask } from 'ember-concurrency';
class MyComponent extends Component {
@task
*plainTask() {}
@dropTask({ cancelOn: 'click' })
*myDropTask() {}
}
Parameters:
Name | Type | Attributes | Default | Description |
---|---|---|---|---|
options |
object |
<optional> <nullable> |
{} | Task modifier options. See task for list. |
- Source:
Returns:
- Type
- Task
dropTaskGroup(optionsopt, nullable) → {TaskGroup}
Turns the decorated property into a task group and applies the
drop
modifier.
Optionally takes a hash of further options that will be applied as modifiers to the task group.
Parameters:
Name | Type | Attributes | Default | Description |
---|---|---|---|---|
options |
object |
<optional> <nullable> |
{} | Task group modifier options. See task for list. |
- Source:
Returns:
- Type
- TaskGroup
enqueueTask(optionsopt, nullable) → {Task}
Turns the decorated generator function into a task and applies the
enqueue
modifier.
Optionally takes a hash of options that will be applied as modifiers to the
task. For instance maxConcurrency
, on
, or group
.
You can also define an
Encapsulated Task
by decorating an object that defines a perform
generator
method.
import Component from '@ember/component';
import { task, enqueueTask } from 'ember-concurrency';
class MyComponent extends Component {
@task
*plainTask() {}
@enqueueTask({ cancelOn: 'click' })
*myEnqueueTask() {}
}
Parameters:
Name | Type | Attributes | Default | Description |
---|---|---|---|---|
options |
object |
<optional> <nullable> |
{} | Task modifier options. See task for list. |
- Source:
Returns:
- Type
- Task
enqueueTaskGroup(optionsopt, nullable) → {TaskGroup}
Turns the decorated property into a task group and applies the
enqueue
modifier.
Optionally takes a hash of further options that will be applied as modifiers to the task group.
Parameters:
Name | Type | Attributes | Default | Description |
---|---|---|---|---|
options |
object |
<optional> <nullable> |
{} | Task group modifier options. See task for list. |
- Source:
Returns:
- Type
- TaskGroup
getModifier(name) → (nullable) {TaskFactory~TaskModifier}
Returns a specified modifier, if it exists in the registry
Parameters:
Name | Type | Description |
---|---|---|
name |
string | Name of the modifier |
- Source:
Returns:
hasModifier(name) → {boolean}
Returns whether a specified modifier exists in the registry
Parameters:
Name | Type | Description |
---|---|---|
name |
string | Name of the modifier |
- Source:
Returns:
- Type
- boolean
keepLatestTask(optionsopt, nullable) → {Task}
Turns the decorated generator function into a task and applies the
keepLatest
modifier.
Optionally takes a hash of options that will be applied as modifiers to the
task. For instance maxConcurrency
, on
, or group
.
You can also define an
Encapsulated Task
by decorating an object that defines a perform
generator
method.
import Component from '@ember/component';
import { task, keepLatestTask } from 'ember-concurrency';
class MyComponent extends Component {
@task
*plainTask() {}
@keepLatestTask({ cancelOn: 'click' })
*myKeepLatestTask() {}
}
Parameters:
Name | Type | Attributes | Default | Description |
---|---|---|---|---|
options |
object |
<optional> <nullable> |
{} | Task modifier options. See task for list. |
- Source:
Returns:
- Type
- Task
keepLatestTaskGroup(optionsopt, nullable) → {TaskGroup}
Turns the decorated property into a task group and applies the
keepLatest
modifier.
Optionally takes a hash of further options that will be applied as modifiers to the task group.
Parameters:
Name | Type | Attributes | Default | Description |
---|---|---|---|---|
options |
object |
<optional> <nullable> |
{} | Task group modifier options. See task for list. |
- Source:
Returns:
- Type
- TaskGroup
rawTimeout(ms)
Yielding rawTimeout(ms)
will pause a task for the duration
of time passed in, in milliseconds.
The timeout will use the native setTimeout()
browser API,
instead of the Ember runloop, which means that test helpers
will not wait for it to complete.
The task below, when performed, will print a message to the console every second.
export default class MyComponent extends Component {
@task *myTask() {
while (true) {
console.log("Hello!");
yield rawTimeout(1000);
}
}
}
Parameters:
Name | Type | Description |
---|---|---|
ms |
number | the amount of time to sleep before resuming the task, in milliseconds |
- Source:
registerModifier(name, callback)
Registers a new modifier with the modifier registry
Parameters:
Name | Type | Description |
---|---|---|
name |
string | Name of the modifier |
callback |
TaskFactory~TaskModifier |
- Source:
restartableTask(optionsopt, nullable) → {Task}
Turns the decorated generator function into a task and applies the
restartable
modifier.
Optionally takes a hash of options that will be applied as modifiers to the
task. For instance maxConcurrency
, on
, or group
.
You can also define an
Encapsulated Task
by decorating an object that defines a perform
generator
method.
import Component from '@ember/component';
import { task, restartableTask } from 'ember-concurrency';
class MyComponent extends Component {
@task
*plainTask() {}
@restartableTask({ cancelOn: 'click' })
*myRestartableTask() {}
}
Parameters:
Name | Type | Attributes | Default | Description |
---|---|---|---|---|
options |
object |
<optional> <nullable> |
{} | Task modifier options. See task for list. |
- Source:
Returns:
- Type
- Task
restartableTaskGroup(optionsopt, nullable) → {TaskGroup}
Turns the decorated property into a task group and applies the
restartable
modifier.
Optionally takes a hash of further options that will be applied as modifiers to the task group.
Parameters:
Name | Type | Attributes | Default | Description |
---|---|---|---|---|
options |
object |
<optional> <nullable> |
{} | Task group modifier options. See task for list. |
- Source:
Returns:
- Type
- TaskGroup
task(optionsopt, nullable) → {Task}
A Task is a cancelable, restartable, asynchronous operation that is driven by a generator function. Tasks are automatically canceled when the object they live on is destroyed (e.g. a Component is unrendered).
Turns the decorated generator function into a task.
Optionally takes a hash of options that will be applied as modifiers to the
task. For instance maxConcurrency
, on
, group
or keepLatest
.
By default, tasks have no concurrency constraints (multiple instances of a task can be running at the same time) but much of a power of tasks lies in proper usage of Task Modifiers that you can apply to a task.
You can also define an
Encapsulated Task
by decorating an object that defines a perform
generator
method.
import Component from '@ember/component';
import { task } from 'ember-concurrency';
class MyComponent extends Component {
@task
*plainTask() {}
@task({ maxConcurrency: 5, keepLatest: true, cancelOn: 'click' })
*taskWithModifiers() {}
}
Parameters:
Name | Type | Attributes | Default | Description | ||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
options |
object |
<optional> <nullable> |
{} | Task modifier options Properties
|
- Source:
Returns:
- Type
- Task
task(generatorFunction) → {TaskProperty}
TODO: update docs to reflect both old and new ES6 styles
A Task is a cancelable, restartable, asynchronous operation that is driven by a generator function. Tasks are automatically canceled when the object they live on is destroyed (e.g. a Component is unrendered).
To define a task, use the task(...)
function, and pass in
a generator function, which will be invoked when the task
is performed. The reason generator functions are used is
that they (like the proposed ES7 async-await syntax) can
be used to elegantly express asynchronous, cancelable
operations.
You can also define an
Encapsulated Task
by passing in an object that defined a perform
generator
function property.
The following Component defines a task called myTask
that,
when performed, prints a message to the console, sleeps for 1 second,
prints a final message to the console, and then completes.
import { task, timeout } from 'ember-concurrency';
export default Component.extend({
myTask: task(function * () {
console.log("Pausing for a second...");
yield timeout(1000);
console.log("Done!");
})
});
<button {{action myTask.perform}}>Perform Task</button>
By default, tasks have no concurrency constraints (multiple instances of a task can be running at the same time) but much of a power of tasks lies in proper usage of Task Modifiers that you can apply to a task.
Parameters:
Name | Type | Description |
---|---|---|
generatorFunction |
function | the generator function backing the task. |
- Source:
Returns:
- Type
- TaskProperty
taskGroup(optionsopt, nullable) → {TaskGroup}
"Task Groups" provide a means for applying
task modifiers to groups of tasks. Once a Task
is declared
as part of a group task, modifiers like drop
or restartable
will no longer affect the individual Task
. Instead those
modifiers can be applied to the entire group.
Turns the decorated property into a task group.
Optionally takes a hash of options that will be applied as modifiers to the
task group. For instance maxConcurrency
or keepLatest
.
import Component from '@glimmer/component';
import { task, taskGroup } from 'ember-concurrency';
class MyComponent extends Component {
@taskGroup({ maxConcurrency: 5 }) chores;
@task({ group: 'chores' })
*mowLawn() {}
@task({ group: 'chores' })
*doDishes() {}
}
Parameters:
Name | Type | Attributes | Default | Description |
---|---|---|---|---|
options |
object |
<optional> <nullable> |
{} | Task group modifier options. See task for list. |
- Source:
Returns:
- Type
- TaskGroup
taskGroup() → {TaskGroup}
"Task Groups" provide a means for applying
task modifiers to groups of tasks. Once a Task
is declared
as part of a group task, modifiers like drop
or restartable
will no longer affect the individual Task
. Instead those
modifiers can be applied to the entire group.
import { task, taskGroup } from 'ember-concurrency';
export default class MyController extends Controller {
@taskGroup({ drop: true }) chores;
@task({ group: 'chores' }) mowLawn = taskFn;
@task({ group: 'chores' }) doDishes = taskFn;
@task({ group: 'chores' }) changeDiapers = taskFn;
}
- Source:
Returns:
- Type
- TaskGroup
timeout(ms)
Yielding timeout(ms)
will pause a task for the duration
of time passed in, in milliseconds.
This timeout will be scheduled on the Ember runloop, which
means that test helpers will wait for it to complete before
continuing with the test. See rawTimeout()
if you need
different behavior.
The task below, when performed, will print a message to the console every second.
export default class MyComponent extends Component {
@task *myTask() {
while (true) {
console.log("Hello!");
yield timeout(1000);
}
}
}
Parameters:
Name | Type | Description |
---|---|---|
ms |
number | the amount of time to sleep before resuming the task, in milliseconds |
waitForEvent(object, eventName)
Use waitForEvent
to pause the task until an event is fired. The event
can either be a jQuery event or an Ember.Evented event (or any event system
where the object supports .on()
.one()
and .off()
).
import { task, waitForEvent } from 'ember-concurrency';
export default class MyComponent extends Component {
@task *myTask() {
console.log("Please click anywhere..");
let clickEvent = yield waitForEvent($('body'), 'click');
console.log("Got event", clickEvent);
let emberEvent = yield waitForEvent(this, 'foo');
console.log("Got foo event", emberEvent);
// somewhere else: component.trigger('foo', { value: 123 });
}
}
Parameters:
Name | Type | Description |
---|---|---|
object |
object | the Ember Object, jQuery element, or other object with .on() and .off() APIs that the event fires from |
eventName |
function | the name of the event to wait for |
- Source:
waitForProperty(object, key, callbackOrValue)
Use waitForProperty
to pause the task until a property on an object
changes to some expected value. This can be used for a variety of use
cases, including synchronizing with another task by waiting for it
to become idle, or change state in some other way. If you omit the
callback, waitForProperty
will resume execution when the observed
property becomes truthy. If you provide a callback, it'll be called
immediately with the observed property's current value, and multiple
times thereafter whenever the property changes, until you return
a truthy value from the callback, or the current task is canceled.
You can also pass in a non-Function value in place of the callback,
in which case the task will continue executing when the property's
value becomes the value that you passed in.
import { task, waitForProperty } from 'ember-concurrency';
export default class MyComponent extends Component {
@tracked foo = 0;
@task *myTask() {
console.log("Waiting for `foo` to become 5");
yield waitForProperty(this, 'foo', v => v === 5);
// alternatively: yield waitForProperty(this, 'foo', 5);
// somewhere else: this.foo = 5;
console.log("`foo` is 5!");
// wait for another task to be idle before running:
yield waitForProperty(this, 'otherTask.isIdle');
console.log("otherTask is idle!");
}
}
Parameters:
Name | Type | Description |
---|---|---|
object |
object | an object (most likely an Ember Object) |
key |
string | the property name that is observed for changes |
callbackOrValue |
function | a Function that should return a truthy value when the task should continue executing, or a non-Function value that the watched property needs to equal before the task will continue running |
- Source:
waitForQueue(queueName)
Use waitForQueue
to pause the task until a certain run loop queue is reached.
import { task, waitForQueue } from 'ember-concurrency';
export default class MyComponent extends Component {
@task *myTask() {
yield waitForQueue('afterRender');
console.log("now we're in the afterRender queue");
}
}
Parameters:
Name | Type | Description |
---|---|---|
queueName |
string | the name of the Ember run loop queue |
- Source: