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. @taskGroup nameOfGroup;
  2. For each task in the group, use @task({ group: ... }) to associate the task with the group, e.g. @task({ group: 'nameOfGroup' }) *myTask() { /* ... */}

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.


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: ()
export default class TaskGroupsController extends Controller {
  @taskGroup({ drop: true }) chores;

  @task({ group: 'chores' }) mowLawn = taskFn;
  @task({ group: 'chores' }) doDishes = taskFn;
  @task({ group: 'chores' }) changeDiapers = taskFn;

  get tasks() {
    return [this.mowLawn, this.doDishes, this.changeDiapers];
{{#each this.tasks as |task|}}
  <button class={{if task.isIdle "clickable"}}
          {{on "click" (perform task)}} type="button">

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

  Most Recent Chore:
  {{#let this.chores.last as |taskInstance|}}
    {{}} ({{taskInstance.state}})

Previous: Child Tasks

Next: Derived State