Pick a Concurrency Strategy
Task Modifiers — restartable, drop, keepLatest
Decorate a task to define how concurrent calls are handled — restart, drop, queue, or keep only the latest.
What you'll learn
- Use restartable for type-ahead inputs
- Use drop for double-submit guards
- Use enqueue or keepLatest where appropriate
A task on its own runs every call to completion. The real power of ember-concurrency is concurrency modifiers — they tell the task what to do when called while a previous run is still in flight.
restartable
Cancel the running instance and start a fresh one. Perfect for type-ahead search:
import { task } from 'ember-concurrency';
searchTask = task({ restartable: true }, async (query) => {
await timeout(300); // debounce
return this.store.query('post', { q: query });
}); Every keystroke restarts the task; only the last query actually fires.
drop
Ignore new perform calls while one is running. Great for save buttons:
saveTask = task({ drop: true }, async () => {
await this.model.save();
}); Double-clicks don’t trigger duplicate saves.
enqueue
Queue new calls and run them one after another:
syncTask = task({ enqueue: true }, async (change) => {
await this.api.push(change);
}); Useful when ordering matters and you can’t lose any calls.
keepLatest
Run the current one to completion, then run only the most-recent queued call, dropping any in between:
fetchTask = task({ keepLatest: true }, async () => {
return this.api.fetch();
}); Good for polling or stale-while-revalidate patterns.
maxConcurrency
Combine with the strategies above to allow N parallel runs:
uploadTask = task({ enqueue: true, maxConcurrency: 3 }, async (file) => {
return this.api.upload(file);
}); Up to three uploads run at once; the rest queue up.
The Router Service →