Defining Tasks with task()

When a task is performed, it runs the code in the async arrow task function you passed into task(). (If you're unfamiliar with async functions and the await keyword, Mozilla has a good introductory guide).

Using the await keyword

Much of the power of Tasks is unleashed once you start making use of the await keyword within async functions. The await keyword, when used with a promise, lets you pause execution of your task function until that promise resolves, at which point the task function will continue running from where it had paused.

This example demonstrates how you can await timeout(1000) to pause execution for 1000 ms (one second). The timeout() helper function, which ember-concurrency provides, simply returns a promise that resolves after the specified number of milliseconds.

waitAFewSeconds = task(async () => {
  this.set('status', 'Gimme one second...');
  await timeout(1000);
  this.set('status', 'Gimme one more second...');
  await timeout(1000);
  this.set('status', "OK, I'm done.");
});

When you await a promise, the await expression evaluates to the resolved value of the promise. In other words, you can set a variable equal to a yielded promise, and when the promise resolves, the task function will resume and the value stored into that variable will be the resolved value of the promise.

myTask = task(async () => {
  this.set('status', `Thinking...`);
  let promise = timeout(1000).then(() => 123);
  let resolvedValue = await promise;
  this.set('status', `The value is ${resolvedValue}`);
});

If you await a promise that rejects, the task function will throw the rejected value (likely an exception object) from the point in task function where the rejecting promise was awaited. This means you can use try {} catch(e) {} finally {} blocks, just as you would for code that runs synchronously.

myTask = task(async () => {
  this.set('status', `Thinking...`);
  try {
    await timeout(1000).then(() => {
      throw 'Ahhhhh!!!!';
    });
    this.set('status', `This does not get used!`);
  } catch (e) {
    this.set('status', `Caught value: ${e}`);
  }
});

Classic Ember use (prior to Ember 3.10+ or non-Ember Octane)

Please see the older guides for how to use ember-concurrency with older versions of Ember.