Derived State

One of the core goals of ember-concurrency is to provide as much Derived State as possible; for example, instead of requiring you to set and then later unset your own isRunning flag at the beginning and end of a task, ember-concurrency gives you an .isRunning (and .isIdle) property for free so that you don't have to manage your own state (which is a common source of bugs and boilerplate).

ember-concurrency gives you the concept of Tasks, and when you perform a Task, it produces a Task Instance, which represents a single execution of that task. Both of these objects expose a lot of derived state, which is described below.

Less commonly-used properties are italicized. Also, keep in mind that there are API docs for everything described below.

Properties on Task objects

  • isRunning: true when there is at least one instance of the task running, false otherwise.
  • isIdle: the opposite of isRunning
  • performCount: The number of times the task has been performed
  • numRunning: an integer representing the number of currently running task instances. If you're using a task modifier like drop/enqueue/restartable (without specifying maxConcurrency) this number will never be greater than 1. This property is mostly useful for debugging.
  • state: a string description of the task's state; can either by "running" or "idle". Useful for debugging.
Accessing Task Instances from the Task object

Tasks also expose properties for accessing specific Task Instances (which are created every time you call .perform() on a task).

  • last: the last Task Instance that started executing. This property will never point to a dropped Task Instance,
  • lastSuccessful: the last Task Instance that ran to completion (it returned a value that wasn't a rejecting promise).

In addition to these properties, keep in mind that at any point you can also just save the TaskInstance returned from .perform() to some property for later access in case the above properties don't hit your use cases (but please open a GitHub issue if you find yourself doing this often because this might suggest room for improvement in ember-concurrency's API).

Properties on Task Instances

  • isSuccessful: true if the Task Instance ran to completion
  • isError: true if Task Instance failed to run to completion due to an exception
  • value: the value returned from the task function. Is null before a value is returned, and remains null if the task never completes (throws an error or is canceled).
  • error: the error/exception thrown from the task function (might also be the value of a rejected promise that was yielded). Note: until this issue is resolved, unless you write code to explicitly .catch() an error thrown from a performed task, this error will bubble to the browser (so error reporters like Bugsnag will see it).

Put the two together...

Given a task named myTask, if you need to display a success banner with the value returned from the most recent execution of myTask, you can simply reference {{myTask.last.value}}. If want this banner to persist until the next time the task runs to completion, you can just change it to {{myTask.lastSuccessful.value}}. There are other combinations as well that might better suit your UI needs.

Live Example

doStuff (performCount=0 numRunning=0)

Completion Property .value .error .isSuccessful .isError
myTask.last
myTask.lastSuccessful
myTask.lastErrored

doStuffDrop (performCount=0 numRunning=0)

Completion Property .value .error .isSuccessful .isError
myTask.last
myTask.lastSuccessful
myTask.lastErrored

doStuffEnqueue (performCount=0 numRunning=0)

Completion Property .value .error .isSuccessful .isError
myTask.last
myTask.lastSuccessful
myTask.lastErrored

doStuffRestartable (performCount=0 numRunning=0)

Completion Property .value .error .isSuccessful .isError
myTask.last
myTask.lastSuccessful
myTask.lastErrored