`.perform()`ing the `task()`

using ember-concurrency

"ember-concurrency is a small but powerful library that supplements Ember's existing tools and conventions for handling concurrency and asynchrony."

- ember-concurrency.com

put simply:

ember-concurrency is analternative to using actions.

actions

ember-concurrency

import { task } from 'ember-concurrency';

export default /**/.extend({
  myAwesomeTask: task(function * () {
    // stuff
  })
});
export default /**/.extend({
  action: {
    myAwesomeAction() {
      // stuff
    }
  }
});

actions

ember-concurrency

<button
  onclick={{perform myAwesomeTask}}
>
  Do something awesome
</button>
<button
  onclick={{action 'myAwesomeAction'}}
>
  Do something awesome
</button>

actions

ember-concurrency

export default /**/.extend({
  coolFunction() {
    this.get('myAwesomeTask').perform();
  }
});
export default /**/.extend({
  coolFunction() {
    this.send('myAwesomeAction');
  }
});

so what does it get you?

tasks have state

<button
  onclick={{perform myAwesomeTask}}
  disabled={{myAwesomeTask.isRunning}}
>
  Do something awesome
</button>

yield beats promise chains beats callbacks

import { task } from 'ember-concurrency';

export default /**/.extend({
  saveSomething: task(function * (something) {
    const isValid = yield validateSomething(something);

    if (!isValid) {
      throwError();
    }

    yield something.save();

    notifyUserThatSomethingWasSaved();
  })
});

tasks can be cancelled manually

import { task } from 'ember-concurrency';

export default /**/.extend({
  interruptSaveSomething() {
    const saveSomething = this.get('saveSomething');

    saveSomething.cancelAll();

    saveSomething.perform(somethingElseToSaveInstead);
  },
  saveSomething: task(function * (something) {
    const isValid = yield validateSomething(something);

    if (!isValid) {
      throwError();
    }

    yield something.save();

    notifyUserThatSomethingWasSaved();
  })
});

tasks can be cancelled automatically

import { task } from 'ember-concurrency';

export default Component.extend({
  saveSomething: task(function * (something) {
    const isValid = yield validateSomething(something);

    // no `if (this.get('isDestroyed')) { return; }` necessary

    if (!isValid) {
      throwError();
    }

    yield something.save();

    // no `if (this.get('isDestroyed')) { return; }` necessary

    notifyUserThatSomethingWasSaved();
  })
});

task modifiers

  • `.restartable()`
  • `.enqueue()`
  • `.drop()`
  • `.keepLatest()`
  • `.maxConcurrency(5)`

downsides

  • Work better on Controllers than Routes because you can bind to their state more easily. (only a downside if you prefer your actions to be on the Route)

examples

is anyone else already using it? how?

questions?

Performing the Task Using ember-concurrency

By Jimmy Lauzau

Performing the Task Using ember-concurrency

An introduction to ember-concurrency, where in your projects are good places to start using tasks, and real-world examples.

  • 1,325