如何在EmberJS中合并(聚合)嵌套模型集合?

iol*_*leo 5 javascript collections ember.js ember-data

考虑这个模型:

Grandparent
  parents: DS.hasMany('parent')

Parent:
  grandparent: DS.belongsTo('grandparent')
  children: DS.hasMany('child')

Child:
  parent: DS.belongsTo('parent')
Run Code Online (Sandbox Code Playgroud)

我想一个计算的属性添加childrenGrandparent模型,其中我希望集合Child模型(Grandparent.children =合并的每个Grandparent.parents.children).

怎么做?

对于此示例数据:

Grandparent { id: 0, parents: [0, 1] }

Parent { id: 0, grandparent: 0, children: [0] }
Parent { id: 1, grandparent: 0, children: [1,2] }

Child { id: 0, parent: 0 }
Child { id: 1, parent: 1 }
Child { id: 2, parent: 1 }
Run Code Online (Sandbox Code Playgroud)

我想要Grandparent.get('children')带有ids [0,1,2]的孩子.

编辑:

App.Grandparent.reopen({
  grandchildren: function(){
    var result = [];
    this.get('parents').forEach(function(parent) {
      parent.get('children').forEach(function(child){
        console.log('is this even called?');
        result.push(child);
      });
      console.log('coz this is!');
    });
    return result;
  }.property("parents", "parents.@each.children")
});
Run Code Online (Sandbox Code Playgroud)

为什么第二个循环为空?我知道数据被加载(ember inspector)..那么为什么这里不能访问?

EDIT2:

差不多了!似乎列表是空的,因为它是一个promise数组(尚未解决),因此在代码执行时 - 它是空的!

 grandchildren: function(){
    var grandchildren = [];
    this.get('parents').forEach(function(parent) {
      var promiseArray = parent.get('children');
      promiseArray.then(function() {
        promiseArray.forEach(function(child){
          grandchildren.push(child);
          console.log(child);
        });
      });
    });
    return grandchildren;
  }.property("parents", "parents.@each.children")
Run Code Online (Sandbox Code Playgroud)

所以这段代码正确地在控制台日志中显示所有的孙子......但是!它仍然没有归还它们.这可能是出于同样的原因 - 当代码命中时return grandparent它仍然是空的.我现在在想,有没有办法解决这个问题?

EDIT3:

似乎问题的根源是DS.hasMany('parent', { async: true })DS.hasMany('child', { async: true }).我已经在原始问题中省略了异步部分,以使模型示例更加清晰.

EDIT4:

我已经通过async: true从DS.hasMany中删除了解决了我的问题并使用此脚本正确加载它们而没有异步.

这解决了"空数组"(未解析的数组)的问题,并允许我访问属性.然后我做了以下代码(在MODEL的重新打开功能中):

grandchildren: function(){
  var res = Ember.ArrayProxy.create({content: Ember.A()});

  this.get('parents').forEach(function(parent){
    res.pushObjects(parent.get('children').toArray());
  });

  return res;
}.property('parents', 'parents.@each.children')
Run Code Online (Sandbox Code Playgroud)

它的工作原理!好极了!

但是,我仍然对ASYNC数据的解决方案感兴趣

下一步是使用从服务器获取的一些数据替换灯具.而且这些数据是异步的......所以我仍然需要一个有承诺的解决方案.

EDIT5:测试代码:

grandchildren: function(){
  var res = Ember.ArrayProxy.create({content: Ember.A()});

  this.get('parents').forEach(function(parent) {
      var promiseArray = parent.get('children');
      promiseArray.then(function() {
        res.pushObjects(promiseArray.toArray());
      });
    });

  return res;
}.property('parents', 'parents.@each.children')
Run Code Online (Sandbox Code Playgroud)

小智 2

您可能正在寻找http://emberjs.com/api/classes/RSVP.html#method_all

var promises = [];
this.get('parents').forEach(function(parent) {
  promises.push(parent.get('children'));
});
return Ember.RSVP.all(promises).then(function(results) {
  // return concatenated results
});
Run Code Online (Sandbox Code Playgroud)

当您调用孙子时,您将得到一个解决串联结果的承诺。

将来看起来会像rails一样支持hasMany。 https://github.com/emberjs/data/issues/120