Loading data via promises


#1

I am working on a habit tracking app. It is written in Ember and backed by CouchDB.

On the main screen I want to show a list of habits and the last time an event was recorded for each. Here are what my models look like:

App.Habit = DS.Model.extend( {
  type: DS.attr('string', { defaultValue: 'habit' } ),
  name: DS.attr( 'string' ),
  color: DS.attr( 'string' ),
  events: DS.hasMany( 'event', { async: true, defaultValue: [] } ),
  style: function() {
    return 'background-color: %@'.fmt( this.get( 'color' ) )
  }.property( 'color' ),
  lastTime: function() {
    return this
      .get( 'events' )
      .then( function( events ) {
        var times = events.map( function( e ) {
          return e.get( 'time' )
        } )
        return times.length == 0 ? undefined : times.sort()[0]
      } )
  }.property( 'events' ),
} )

App.Event = DS.Model.extend( {
  type: DS.attr('string', { defaultValue: 'event' } ),
  time: DS.attr( 'date' ),
  habit: DS.belongsTo( 'habit' )
} )

Note that the lastTime property of Habit, returns a promise. When I did it without the promise the array was length 0. My handlebars template looks like:

<script type="text/x-handlebars" id="habits">
  <div id="habits">                                                                                                                                                                                        
    {{#each}}                                                                                                                                                                                              
      <div class="row" {{action 'createEvent' id}}>
        <div class="col-xs-1 color" {{bind-attr style=style}}></div>
        <div class="col-xs-8">{{name}}</div>
        <div class="col-xs-3" data-role="timer">{{format-time-numeric lastTime}}</div>
      </div>                                                                                                                                                                                               
    {{/each}}                                                                                                                                                                                              
  </div>
</script>

The format-time-numeric helper is just:

Ember.Handlebars.registerBoundHelper( 'format-time-numeric', function( time ) {
  return moment( time ).format( 'YYYY/M/D @ H:mm' )
} )

The time getting passed to moment is a promise and is rendering as a bunch of NaNs. If I pass a promise back from format-time, it renders as [object].


#2

This was finally answered on stackoverflow using a reduceComputed property.