An alternative Ember Data store that returns Ember Concurrency tasks instead of promises.
ember install ember-data-tasks
This addon comes in three phases:
- Phase 1: Store Override
- Phase 2: Model Override
- Phase 3: Custom Endpoints, like ember-api-actions, but with tasks (coming soon).
By overriding the store with a mixin, we extend the behavior of methods on the store, like store.findRecord('post', 1)
.
Override your existing store, by creating a new store (or use your existing one, if you have it):
ember g service store
Open app/services/store.js
and modify it to:
import DS from 'ember-data';
import TaskStoreMixin from 'ember-data-tasks/mixins/task-store';
export default DS.Store.extend(TaskStoreMixin);
Now you can use your Ember Data store like before, and nothing has changed, since this
store is backwards compatible, due to the fact that tasks
also adhere to the promise spec.
But you didn't come here for the same old, you want immediate results. To take advantage of the benefits of tasks, you will have to wrap your store responses in a hash.
The example below will hit afterModel
after the backend has resolved with data:
import Ember from 'ember';
export default Ember.Route.extend({
model() {
return this.store.findAll('post');
}
});
But if you want immediate responses, do the following, and afterModel
will
be hit immediately:
import Ember from 'ember';
export default Ember.Route.extend({
model() {
return {
postsTask: this.store.findAll('post')
};
}
});
Then you can utilize the task
in your template like so:
This seems like a slight annoyance at first, due to the extra level of nesting, but
in the end if you build ambitious apps, you will most likely return multiple
tasks, and would have used Ember.RSVP.hash
anyway, if working with promises.
Note: You can unwrap the task hash in setupController
, if it really bothers you.
This phase allows you to enable tasks for methods like model.save()
.
Open app/models/my-model.js
and modify it to:
import DS from 'ember-data';
import TaskModelMixin from 'ember-data-tasks/mixins/task-model';
export default DS.Model.extend(TaskModelMixin, {
// your model definition
});
You'd have to do this for every model, and if you have few, that should be easy. For those that have many models, you can do the following:
Reopen the DS.Model
in your app/app.js
file.
import Ember from 'ember';
import Resolver from './resolver';
import loadInitializers from 'ember-load-initializers';
import config from './config/environment';
// Add these two imports
import DS from 'ember-data';
import TaskModelMixin from 'ember-data-tasks/mixins/task-model';
let App;
Ember.MODEL_FACTORY_INJECTIONS = true;
App = Ember.Application.extend({
modulePrefix: config.modulePrefix,
podModulePrefix: config.podModulePrefix,
Resolver
});
loadInitializers(App, config.modulePrefix);
// Add this model reopen
DS.Model.reopen(TaskModelMixin);
export default App;
Now you can call model.reload()
, model.save()
, and model.destroyRecord()
and get
tasks back instead of promises.