Ember.js如何正确初始化localstorage-adapter? (hasMany with async:true不会保留)

时间:2014-09-09 10:23:58

标签: ember.js local-storage

我正在使用带有localstorage-adaper.js的ember.js。

我的问题始于一个已经回答的问题:EmberJS - record with hasMany relation fails to load

所以有模特:

 // Models
    App.List = DS.Model.extend({
        name: DS.attr('string'),
        items: DS.hasMany('item')
    });  

    App.Item = DS.Model.extend({
        name: DS.attr('string') ,
        list: DS.belongsTo('list')
    });

当#/ list / 1模板被渲染时,页面上没有显示这些项目,并且在控制台中抛出了断言失败:

Assertion failed: You looked up the 'items' relationship on 'App.List:ember236:1' but some of the associated records were not loaded. Either make sure they are all loaded together with the parent record, or specify that the relationship is async (DS.attr({ async: true }))

根据规定,解决方案是使hasMany async像这样:

App.List = DS.Model.extend({
  name: DS.attr('string'),
  items: DS.hasMany('item',{async:true})
}); 

它非常适合这种情况!

下一步:

我正在从服务器加载数据并在应用程序首次加载时将其推送到商店:(您可以在此处找到示例的JSBin:http://jsbin.com/lejizo/1/

var data = { //in real life this is fetched through an AJAX request

      'list': { id: '1', name: 'The List', items: ['1','2'] },
      'items': {
          '1': { id: '1', name: 'item 1', list: '1' },
          '2': { id: '2', name: 'item 2', list: '1' }
        }
      };

...

this.store.push('list', data.list).save();
this.store.pushMany('item', data.items).forEach(function (item) {
     item.save();
});

设置async:true选项后,我注意到item ID不再存在于localstorage中。 JSON看起来像这样:

{"App.List":{"records":{"1":{"id":"1","name":"The List","items":[]}}},"App.Item":{"records":{}}}

显然这些项目没有显示,因为没有参考。

我可能会认为我应该找到另一种方法来填充locastorage!怎么样?
或者这种情况还有另一种解决方法吗?

2 个答案:

答案 0 :(得分:1)

aync:true关系旁边的hasMany关系中,外键没有被持久保存到本地区域,这也会导致控制器内部出现其他问题。你得到的是Promise,而不是实际的对象,所以你总是必须使用list.get('items').then(/*code here*/)(查看我发布的Ember local-storage How to use hasMany with async: true in controllers?这个问题),在某些情况下,你在循环中使用它可能会导致计算器。

使用localstorage,您将始终拥有客户端的所有数据。使用async是真的没有意义:true。问题是,ember需要list.items的一组vanilla对象,而不仅仅是id。这里描述DS.FixtureAdapter loses fixture data with hasMany async attributes

有一种简单的解决方法可以摆脱async:true关系中的hasMany。请注意,您在localstorage中拥有所有需要的数据!如果Ember看到内存存储区中的项目,则不再抛出:"Assertion failed: You looked up the 'items' relationship on 'App.List:ember236:1' but some of the associated records were not loaded..."错误。

解决方案:

Ember.Route.reopen({
    beforeModel: function(transition){
        this.store.find('list');
        this.store.find('items');
    }
});

我们覆盖Ember.Route对象,因此我们在beforeModel挂钩中调用store.find('object')。这样做迫使Ember将数据从localstorage加载到“in memory”存储中!您将不再需要async:true,也不会抛出任何错误。此外,在第一次初始化时,外键也将被保留!

每次都必须这样做(在Route超级类中),因为你永远不知道刷新将在哪条路径上发生。此外,对于具有多达50个记录的~10个型号的商店,它在~50-70ms内运行。如果在您的方案中看起来很多,请确保仅在您想要的路线上进行此呼叫,并且仅针对所需的模型。

此外,如果您覆盖路线中的beforeModel,请务必致电

this._super(transition)

希望这有帮助!

答案 1 :(得分:0)

您错误地定义了数据,请尝试以下操作:

var data = { //in real life this is fetched through an AJAX request

      'list': { id: '1', name: 'The List', items: [1,2] },
      'items': [
          { id: '1', name: 'item 1', list: '1' },
          { id: '2', name: 'item 2', list: '1' }
      }];
}

首先,您的物品前面不需要索引1,2,.... 第二个hasMany关系应该返回一个数组,这就是items将数据包装为数组的原因。 因此,要解决您的问题,您必须修复服务器中的数据,或编写序列化程序来按摩数据。

希望它有所帮助!