如何用链接重新加载异步hasMany关系?

时间:2013-11-14 16:48:42

标签: javascript ember.js ember-data

让我们说

Post = DS.Model.extend({
  comments: DS.hasMany({async: true})
})

Comment = DS.Model.extend({
  post: DS.belongsTo()
})

我必须使用links功能,否则由于对帖子的评论过多而导致414错误。

此提交https://github.com/emberjs/data/commit/4d717bff53f8c93bedbe74e7965a4f439882e259

似乎无法触发post.get('comments')的重新加载,即发送GET请求,例如post / 42 / comments。

有没有解决方案?

6 个答案:

答案 0 :(得分:15)

<强>更新

就像@ sly7_7在下面的回答中所说,这个功能现在可以在ember-data中使用了。因此,如果您使用的是1.0.0-beta.11或更高版本,则不需要此代码

您可以重新打开ManyArray,并创建一个名为reloadLinks()的新方法。有以下内容:

var get = Ember.get;

DS.ManyArray.reopen({
    reloadLinks: function() {
        var records = get(this, 'content'),
        store = get(this, 'store'),
        owner = get(this, 'owner'),
        type = get(this, 'type'),
        name = get(this, 'name'),
        resolver = Ember.RSVP.defer();

        var meta = owner.constructor.metaForProperty(name);
        meta.type = type;
        var link = owner._data.links[meta.key];
        store.findHasMany(owner, link, meta, resolver);
    }
});

用法如下:

comments.reloadLinks();

看看那个小提琴http://jsfiddle.net/H6Gqf/

答案 1 :(得分:7)

感谢@igorT,这是实现的。 https://github.com/emberjs/data/pull/2297

现在ManyArray有一个reload()方法,如果尚未加载关系,你甚至可以调用它。

您可以通过阅读tests

来查看一些用例

答案 2 :(得分:2)

重新加载hasMany还没有直接内置到Ember Data中,但它已经开始了。我使用的解决方案需要Ember Data 1.0b9 + canary,其中包括opt-in coalesced finds

第1步:选择加入。

我已选择在ApplicationAdapter级别,但您可能希望在每个型号的适配器基础上执行此操作。这就是我所拥有的:

MyApp.ApplicationAdapter = DS.ActiveModelAdapter.extend({
  coalesceFindRequests: true
});

为了让您了解为什么这很重要且很好,我们的应用上的一个页面在此更改之前会看到50多个请求。我们现在只看到11.它仍然不是很好,但这是一个改进的地方!

第2步:重新加载协会中的记录

我只是简单地在我的模型上的函数中重新加载:

MyApp.SomeModel = DS.Model.extend({
  fooMany: DS.hasMany('foo', { async: true }),
  barMany: DS.hasMany('bar', { async: true }),
  bazOne: DS.belongsTo('baz', { async: true }),

  reloadAssociated: function () {
    var foosPromises = this.get('foos').invoke('reload'),
        barsPromises = this.get('bars').invoke('reload'),
        bazPromise = this.get('baz').reload();

    return Em.RSVP.hash({
      foos: foosPromises,
      bars: barsPromises,
      baz: bazPromise
    });
  }
});

我承认它并不是非常漂亮,但它是我提出的最佳解决方案,直到重新加载直接构建到关联中。

答案 3 :(得分:1)

我遇到了同样的问题而且我被骗了找到一个“解决方案”

我创建了一个组件“CommentLoader”。该组件采用一个参数(post_id)和 在“插入”(willInsertElement)之前,我将所有注释都渲染并渲染它们。它有效,但......我并不为此感到骄傲:(

答案 4 :(得分:1)

使用 ember-data-1.0.0-beta.10 我正在使用以下型号扩展程序。

只需调用model.reloadRelationship(name),其中name是表示关系的model属性的名称。

这适用于普通和链接belongsTo / hasMany关系。

DS.Model.reopen({
    reloadRelationship: function(name) {
        var meta = this.constructor.metaForProperty(name),
            link = this._data.links ? this._data.links[meta.key] : null;
        if (!link) {
            if (meta.kind === 'belongsTo') {
                this.get(name).then(function(model) { model.reload(); });
            } else {
                this.get(name).invoke('reload');
            }
        } else {
            meta.type = this.constructor.typeForRelationship(name);
            if (meta.kind === 'belongsTo') {
                this.store.findBelongsTo(this, link, meta);
            } else {
                this.store.findHasMany(this, link, meta);
            }
        }
    }
});

这里唯一缺少的是一些检查,例如检查模型是否已经通过链接重新加载模型时重新加载,或者检查当前模型中是否存在属性名称。

编辑ember-data-1.0.0-beta.14:

DS.Model.reopen({
    reloadRelationship: function(key) {
        var record = this._relationships[key];
        if (record.relationshipMeta.kind === 'belongsTo') {
            return this.reloadBelongsTo(key);
        } else {
            return this.reloadHasMany(key);
        }
    },
    reloadHasMany: function(key) {
        var record = this._relationships[key];
        return record.reload();
    },
    reloadBelongsTo: function(key) {
        var record = this._relationships[key];
        if (record.link) {
            return record.fetchLink();
        } else {
            record = this.store.getById(record.relationshipMeta.type, this._data[key]);
            return record.get('isEmpty') ? this.get(key) : record.reload();
        }
    }
});

HasMany关系将回退到本机重新加载方法。

对于BelongsTo关系,它将首先检查是否需要重新加载记录(如果它尚未加载,它将只调用get来检索记录,否则它将调用reload)。

答案 5 :(得分:0)

另一种选择是向模型添加方法。也适用于hasMany:

search: DS.belongsTo('search', {async: true})

updateSearch: ->
  resolver = Ember.RSVP.defer()
  resolver.resolve = =>
    # do something after promise resolves
  relationship = @constructor.metaForProperty('search')
  link = @_data.links[relationship.key]
  @store.findBelongsTo this, link, relationship, resolver