Loading UI While a Task is Running

Reining in undesired concurrency is partly what ember-concurrency has to offer. The other part is making it easy to build UI around asynchronous tasks.

For simple cases where you just need to display a loading dialog or disable a button while a task is running, you can make use of the .isIdle property of a task. This property is false when the task is running, and true otherwise. This eliminates a lot of the boilerplate of setting a property at the beginning of some async operation, and unsetting when the operation completes. Also, because the task in the example below uses the drop() modifier (see Managing Task Concurrency), there's no need to write a guard at the beginning of the task to return early if the task is already running.

Live Example

What is the meaning of life?

export default Controller.extend({
  askQuestion: task(function * () {
    yield timeout(1000);
    this.set('result', Math.random());
  }).drop(),

  result: null,
});
<button class={{if askQuestion.isIdle 'button-primary'}}
  onclick={{perform askQuestion}}>
      {{#if askQuestion.isIdle}}
        Ask
      {{else}}
        Thinking...
        {{loading-spinner}}
      {{/if}}
</button>