Yieldables

Starting with ember-concurrency v2.1.0, Yieldables are a new addition to the public API to provide a way to instrument TaskInstances. The API provides a safe mechanism to implement custom waiters, hooks, introspection, and other operations in a task definition, from application code.

There are many great uses for yieldables, and indeed many of them are already built-in to ember-concurrency today. Yieldables like animationFrame, timeout, and rawTimeout provide safe, cancelation-aware ways to delay execution of a task. Cancelable Promise helpers like all, and hashSettled are too a form of yieldable.

While there are many built-in forms that provide cancelation-aware wrappers around common browser APIs, you can also define domain-specific yieldables for use within your application or complementary addons. This allows you to implement behavior that would be inappropriate for inclusion in ember-concurrency itself.

Defining a new yieldable

Let's suppose you want to create a Task-aware, cancelable wrapper for the requestIdleCallback browser API, in order to write tasks that pause until the browser has time to execute some lower-priority tasks.

// app/yieldables/idle-callback.js
import { Yieldable } from 'ember-concurrency';

class IdleCallbackYieldable extends Yieldable {
  onYield(state) {
    let callbackId = requestIdleCallback(() => state.next());

    return () => cancelIdleCallback(callbackId);
  }
}

export const idleCallback = () => new IdleCallbackYieldable();

export default idleCallback;

Now that we have a yieldable defined, we can import and use it in any tasks that we wish.

import Component from '@glimmer/component';
import { task } from 'ember-concurrency';
import idleCallback from 'my-app/yieldables/idle-callback';

export class MyComponent extends Component {
  @task *backgroundTask() {
    while (1) {
      yield idleCallback();

      const data = this.complicatedNumberCrunching();
      yield this.sendData(data);
    }
  }
}

More about Yieldables

The behavior and implementation of yieldables are defined further in the Yieldables RFC. Additionally, the API for Yieldable is documented here.