Previous: Child Tasks

Next: Derived State

Task Groups

While Task Modifiers prevent a single task from running concurrently, Task Groups make it possible to prevent multiple tasks from running at the same time. Using Task Groups is a two-step process:

  1. Define the task group property, e.g. nameOfGroup: taskGroup()
  2. For each task in the group, use .group() to associate the task with the group, e.g. myTask: task(...).group('nameOfGroup')

Once you define a task as part of a task group, you can no longer use other task modifiers like drop() or restartable() on that task; instead, just apply those task modifiers to the task group property instead, as demonstrated in the example below.

Example

In this example, we group related "chores" tasks and by using the .drop() modifier on the taskGroup property we ensure that only one chore task runs at a time. In addition to preventing concurrency between multiple tasks, this example also demonstrates how having access to both the state of the task group, as well as its individual members, makes it very easy to build out common UI patterns, such as active/idle states of related buttons in a button bar.

Chores group state: idle
Most Recent Chore:
import { task, taskGroup } from 'ember-concurrency';

export default Controller.extend({
  chores: taskGroup().drop(),

  mowLawn:       task(taskFn).group('chores'),
  doDishes:      task(taskFn).group('chores'),
  changeDiapers: task(taskFn).group('chores'),

  tasks: computed(function() {
    return [
      this.get('mowLawn'),
      this.get('doDishes'),
      this.get('changeDiapers'),
    ];
  }),
});
{{#each tasks as |task|}}
  <button class={{if task.isIdle 'clickable'}}
          onclick={{perform task}}>{{task.name}}</button>
{{/each}}

<h5>Chores group state: {{chores.state}}</h5>

<h5>
  Most Recent Chore:
  {{#with chores.last as |taskInstance|}}
    {{taskInstance.task.name}} ({{taskInstance.state}})
  {{/with}}
</h5>




Previous: Child Tasks

Next: Derived State