Store Returns Empty Object on Call from Action


#1

Hi all, I am pretty new to Ember and i encountered a problem which I worked around but I am very curious about it. I have the following route:

export default Ember.Route.extend( {
   model: function(params) {
      this.store.unloadAll('apiary');
      this.store.unloadAll('beehive');
      this.store.adapterFor('beehive').set('namespace', 'api/v1/apiaries/' + params.apiary_name.replace(/ /g, "."));
     var hives = this.store.find('beehive');
     this.store.adapterFor('beehive').set('namespace', 'api/v1');
     return Ember.RSVP.hash({
             apiary: this.store.find('apiary', params.apiary_name.replace(/ /g, ".")),
             beehives: hives
  });

},
actions:{
showLineChart: function(type, beehiveId) {      
  var self=this;   
  self.controller.set('lineChartData', this.store.find('beehive_inspection', {by_beehive: beehiveId})); // returns nothing
  this.store.find('beehive_inspection', {by_beehive: beehiveId}).then(function(a) {
    self.controller.set('lineChartData', a.get('content')); //returns ok 
  });
}

} });

The model hook works just fine and returned all the data correctly. However when the showLineChart action is called (from a component) if I try to access the store again using store find without handling its response, the returned value is always empty although i can see the request is made in my back end. To get the data i had to handle the response and get its content. Any idea why this happens ?


#2

How I understand it, although I could be mistaken:

The model hook expects to return a promise, so it handles the promise behind the scenes to get the data from it. When accessing data returned through promises in most other cases, eg. with find(), you need to explicitly handle the promise and act on the result.

Ember.set expects a value, not a promise, so the promise gets set as the value, not the data returned from the server by the prom. As you have it in your first example, I would expect that inspecting lineChartData in the controller would reveal the promise object, not the data or nothing.

Presumably (although I haven’t tested it) you may be able to do something like

showLineChart: function(type, beehiveId) {      
  var self=this;   
  self.controller.set('lineChartData', this.store.find('beehive_inspection', {by_beehive: beehiveId}).then(function(resp){ return resp.get('content'); }));
}

(handle the promise inside the set) but that’s really hard to read (I’m not sure I have all the parentheses correct), fragile even if it does work (what if the promise returns a failed result?), and I definitely don’t recommend it. I’d stick with setting the property inside the promise handler as you have in your second example.

A general rule of thumb is that if a method doesn’t expect a promise, it won’t know what to do with one.