Menu iconMenu

If you don’t know ember-concurrency…Recommended reading: This article by Alex Matchneer or watch this video on the ember concurrency website. Play with these examples.

Right, for those who want to crack on, let’s get into it!

Not everything is as it seems

Nominally, the .drop()  task modifier in ember-concurrency indicates that no more than one instance of a task may ever be running once at a time. However, you might have missed this crucial sentence from a page deep down in the Route Tasks page of the documentation:

“ember-concurrency tasks are scoped to the lifetime of the object they live on, so if that object is destroyed, all of the tasks attached to it are cancelled.”

The important takeaway here is the first bit: “ember-concurrency tasks are scoped to the lifetime of the object they live on”. i.e. ember-concurrency tasks are scoped to object instances, not classes.

As you’ll see below, you can actually have multiple instances of a task running simultaneously, despite having applied a modifier (drop, enqueue, restartable, keepLatest) to prevent that from happening. This applies to all of the task modifiers, but we’ll just stick with drop in our examples to keep things simple.

Take the following component (view the full twiddle example here):

What’s going on?

In the application.hbs template, we’ve rendered out the component twice. Since ember-concurrency tasks are scoped to instances (in this case, instances of a component), each rendered component gets its own, unique instance of myTask .

Each instance of myTask  keeps its own completely independent state, and that enables us to perform myTask  on both components simultaneously. To demonstrate: if we were to double-click Button One we see the text Running pop up next to Button One (but not Button Two) and we only see a single pair of logs in the console:

  • Start One
  • Done One

That’s ember-concurrency doing its job for us by preventing the task from being run a second time while the first is still running.

However, the same rule does not apply when we click Button Two immediately after Button One. When doing that, we see Running show up next to both buttons, and the following in the console:

  • Start One
  • Start Two
  • Done One
  • Done Two

Enter the Singleton

If necessary, we can get around this duplication effect by defining our tasks in singletons. In Ember, routes, controllers and services are all singletons, meaning only a single instance of any given route, controller, or service is created. Once created, they are never destroyed.

The obvious connection to ember-concurrency tasks is: if I had defined myTask on a route instead of in a component, it would not have been duplicated. In that case, we truly would only ever have one instance of myTask  running at a time, regardless of how many times or combinations of buttons we pressed.
And there you have it! This behaviour by ember-concurrency is definitely a sane default and likely the most commonly used behaviour. On the rare occasion you do need multiple sibling components to share task state, it could cause some unexpected bugs in your application if you’re not paying attention.

Ember Blueprints: why they’re awesome

Brit-turned-Queenstowner and keen coder Jonathan on why he's a fan of Ember Blueprints. Note: This is part one of a. . . (yet-to-be-decided-how-many-parts) series on this subject.
Jonathan H Posted by Jonathan H on 11 August, 2017

Managing Relations in Ember Data with JSON API

From his villa in beautiful Bali, our nomad developer Patrick weighs in on this technical issue. He even provides demo-code.
Patrick Posted by Patrick on 18 August, 2017

Displaying Promises in EmberJS Templates

Brewer/developer/juggler Ewen Cumming on how to use promises in EmberJS templates.
Ewen Posted by Ewen on 19 October, 2016
Comments Comments
Add comment

One Reply to “A Day in the Life of an Ember Concurrency Task…”

Leave a Reply

Your email address will not be published.