延迟加载会导致Ember中的未定义数据

时间:2015-09-21 12:41:39

标签: ember.js ember-data

我使用ember.js一周,遇到了有关ember-data和ember.js的问题。我在名为User的模型上有一个简单的1:N关系。 User有多个Slots,由start_timeend_time定义。

在名为slots-per-day的组件中,给定用户的所有插槽都按日过滤,并使用以下js代码:

  /* ... rest of component.js of slots-per-day ... */
  filteredSlots: Ember.computed('user', function() {
    let time = moment();
    return this.get('user.slots').filter( (slot) => {
      let left = moment(time).startOf('day');
      let right = moment(time).endOf('day');
      let start_time = moment(slot.get('start_time'));
      let end_time = moment(slot.get('end_time'));
      console.debug(slot.get('start_time'));

      return start_time.isBetween(left, right) || end_time.isBetween(left, right);
    });
  })
  /* ... rest of component.js of slots-per-day ... */

我遇到了不同方法的几个问题:

  1. 使用上面的代码filterSlots-property仅评估一次。底层存储处于未定义状态,因为console.debug输出undefined但插槽数量恰到好处。所以我猜ember-data已经为插槽加载了数组,但忘记了来加载其余的数据。如果我转换到同一路线,所有数据都会正确显示,console.debug会返回不同的moment.js-dates。

  2. 如果我将user.slots添加到该属性的依赖项列表中,则会评估两次。两次评估都会产生与(1)中相同的调试输出:undefined

  3. 如果我添加user.slots.@each.start_time,则会评估该属性,该页面上的组件数乘以插槽数量(这非常慢)。尽管它很慢,但它可以正常工作并呈现数据。

  4. 所以问题是:如何在渲染组件之前预加载ember-data中的所有数据?

    修改

    我也尝试过承诺:

      /* SlotRoute ... */    
      setupController(controller, model){
        this._super(controller, model);
        controller.set('time', this.get('time'));
        controller.set('users', model.users);
        controller.set('timeScope', this.get('timeScope'));
      },
    
      users: Ember.computed('time', function() {
        return this.store.query('user', {
          slots: {
            time: this.get('time').toString(),
            timeScope: this.get('timeScope')
          }
        });
      }),
    
      model(params) {
        return Ember.RSVP.hash({
          users: this.get('users'),
          slots: this.store.get('slots')
        });
      },
      /* ... */
    

    上述列表的位置(1),(2)和(3)没有变化。

1 个答案:

答案 0 :(得分:0)

编号3是编写计算属性的正确方法,尤其是异步关系。您必须在某个地方支付价格,如果您想在转换期间支付它,您可以使用afterModel假设您使用model挂钩获取用户。如果它在其他地方加载,您也可以使用该特定路线的afterModel / beforeModel

路线

model(params){
  return this.store.find('user', 1);
},
afterModel(model, transition){
  return model.get('slots');
}

使用某种服务的路线

afterModel(model, transition){
  return this.get('someservice.user.slots');
}