Lazy loading async relations in Ember

In ember models you can define if a relation is async or not by adding {async: true}, after the relation. The point of that option depends on your adapter but in most cases means that your backend returns the ids of the relations instead of embedding them in the initial resource.

But still, sometimes ember will go and fetch all of them even if you need only one of them.

For instance the other day I had the following code:

{ {#link-to 'fault.exception' fault fault.exceptions.firstObject}}
  { {fault.eClass}} in { {fault.filepath}}:{ {fault.line}}<br>
  { {fault.message}}
{ {/link-to}}

fault model has many exceptions. I needed only the first exception but ember would send a banch of requests:

//model request
Started GET "/rack-reqorder/api/v1/faults?per_page=1&sort%5Bupdated_at%5D=desc" for 127.0.0.1 at 2015-07-22 13:06:23 +0300

//requests generated by the template
Started GET "/rack-reqorder/api/v1/exceptions/55ae0bb44d61632688720600" for 127.0.0.1 at 2015-07-22 13:06:24 +0300
Started GET "/rack-reqorder/api/v1/exceptions/55ae0bc64d61632688750600" for 127.0.0.1 at 2015-07-22 13:06:24 +0300
Started GET "/rack-reqorder/api/v1/exceptions/55ae0bdd4d61632688ec0600" for 127.0.0.1 at 2015-07-22 13:06:24 +0300
Started GET "/rack-reqorder/api/v1/exceptions/55ae0c184d61632688430700" for 127.0.0.1 at 2015-07-22 13:06:24 +0300
Started GET "/rack-reqorder/api/v1/exceptions/55ae0bf04d61632688150700" for 127.0.0.1 at 2015-07-22 13:06:24 +0300
Started GET "/rack-reqorder/api/v1/exceptions/55ae0c014d616326883e0700" for 127.0.0.1 at 2015-07-22 13:06:24 +0300
Started GET "/rack-reqorder/api/v1/exceptions/55ae0c214d61632688460700" for 127.0.0.1 at 2015-07-22 13:06:24 +0300
Started GET "/rack-reqorder/api/v1/exceptions/55ae0c524d616326884b0700" for 127.0.0.1 at 2015-07-22 13:06:24 +0300
Started GET "/rack-reqorder/api/v1/exceptions/55ae0c7c4d616326884e0700" for 127.0.0.1 at 2015-07-22 13:06:24 +0300

Ember here sees that you need the has many relation of fault and fetches all the exception ids that were found in the fault resource making the whole app slower.

How can we mitigate this? It turns out that we can retrieve the exception ids of each fault model. They are hidden under _data.exceptions (actually under _data you can find all data that server returned for that resource). All you need to do is to add a computed property for that and with an Ember enumerator return an array of the ids.

  exceptions: DS.hasMany('exception', {async: true}),
  exception_ids: function() {
    return this.get('_data.exceptions').map(function(item) { return item.id; });
  }.property('exceptions')

Similarly to get the id of a belongsTo relation:

  fault: DS.belongsTo('fault', {async: true}),
  fault_id: function() {
    return this.get('_data.fault');
  }.property('fault'),

Now using the ember link-to helper with a model id, ember won't fetch the model until user clicks on it. And even then, ember will fetch only that child model and not all child models for that relation.

Loading comments…
All rights reserved