App.Foo = DS.Model.extend({ bar: belongsTo('bar',{ async: true}) }); App.Bar = DS.Model.extend({ foos: hasMany('foo',{ async: true}) });
我的路由代码中的情况触发了请求,当响应返回时,我访问相关的“bar”模型,因为我过滤了/ etc
this.store.all('foo').clear(); var fooz = self.store.all('foo'); //new code return this.store.find('foo').then(function(response) { var filtered = response.filter(function(foo) { return foo.get('bar').get('name') === 'bazz'; }); //other code that would normally be executed top-down //including side-effect stuff like this //self.store.createRecord('foo',someHash); return fooz; //new code });
上面的第一次不起作用,因为foo.get(‘bar’)是一个承诺.但这只是第一次遇到的问题(随后的$.ajax请求似乎已经缓存了所有bar对象,所以这是一个非问题)
奇怪的是,在我启动应用程序之前,我已经删除了init中的所有条形数据(如下所示).那么为什么在技术上数据应该已经在本地存储的情况下,为什么ember-data甚至需要解决“bar”的承诺呢?
App.initializer({ name: 'bootstrap',initialize: function() { App.deferReadiness(); var store = App.__container__.lookup("store:main"); var bars = store.find('bar'); var configurations = store.find('configuration'); Ember.RSVP.all([bars,configurations]).then(results) { App.advanceReadiness(); }); } });
解决方法
存储缓存
this.store.all('foo').clear();
只是打破内部所有过滤器,直到修改/添加/删除foo记录,强制过滤器重新计算存储中的记录.我这样说是为了表明清除不是从ED商店删除记录.
示例(单击按钮,观看控制台,阅读有趣的动作代码)
http://emberjs.jsbin.com/OxIDiVU/103/edit
这就是说它不是被缓存的ajax,它是记录实例上被缓存的属性/关系(和记录).
从商店中删除类型记录的正确方法是store.unloadAll(‘foo’)
Promiselandia
我知道你已经熟悉了承诺,所以这部分可能毫无价值,但值得记录
异步关系非常酷,因为它们为belongsTo / hasMany返回PromiSEObject / PromiseArray. PromiSEObject / PromiseArray扩展ObjectProxy / ArrayProxy(这些与ObjectController / ArrayController扩展相同).这实质上使PromiSEObject / PromiseArray能够代理获取/设置属性到下面的模型.在这种情况下,承诺上的设置/获取不会“工作”,直到承诺得到解决(它不会崩溃,只返回undefined). *警告,承诺中不存在方法,因此您无法调用保存承诺并期望它能够正常工作.
防爆.使用你的模型.
var foo = this.store.find('foo',1); var bar = foo.get('bar'); // PromiSEObject bar.get('name'); // undefined
后来,bar已经解决了,bar仍然是PromiSEObject
bar.get('name'); // billy
foo将继续返回PromiSEObject
var bar2 = foo.get('bar'); // PromiSEObject bar2.get('name'); // billy
保存
bar.save(); // Boom no workey bar.then(function(realBar){ realBar.save(); // workey });
在你的情况下,我有3个建议
建立你自己的承诺,在你想要的时候解决,在所需的记录上使用Ember.RSVP.all(尊重他们可能会或可能不会解决,因此异步)
var self = this; var promise = new Ember.RSVP.Promise(function(resolve,reject){ self.store.find('foo').then(function(foos) { Em.RSVP.all(foos.getEach('bar')).then(function(bars){ var filtered = bars.filterBy('name','bazz'); resolve(filtered); }); }); }); return promise;
http://emberjs.jsbin.com/OxIDiVU/104/edit
异步属性
很多时候,在模型钩子期间没有解析的异步对象/属性(在promises上阻塞并等待它们被解析)一个好方法是设置占位符对象等.
var items = []; controller.set('model',items); // promise from above promise.then(function(records){ items.pushObjects(records.toArray()); // toArray may or may not apply });