【问题标题】:How to reload an async with links hasMany relationship?如何重新加载带有链接 hasMany 关系的异步?
【发布时间】:2013-11-27 19:22:51
【问题描述】:

假设我们有

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

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

我必须使用links 功能,否则我会因为帖子中的 cmets 太多而收到 414 错误。

自从这次提交https://github.com/emberjs/data/commit/4d717bff53f8c93bedbe74e7965a4f439882e259

似乎不可能触发 post.get('cmets') 的重新加载,例如在 post/42/cmets 上发送 GET 请求。

有什么解决办法吗?

【问题讨论】:

  • 我认为解决这个问题的更好方法是在ManyArray 类中覆盖RecordArray 中的update 方法。并给出一些上下文,比如links。目前使用comments.update() 将获取所有的cmets,而不是'post/1/cmets'。但要做到这一点,需要一些拉取请求。
  • 是的,作为第一次尝试,我尝试使用更新方法;)。我很想听听@wycats 关于这个 PR 建议。
  • 这是作为 PR 提交的吗?
  • 感谢@igorT,现在才推送到master:github.com/emberjs/data/pull/2297请尝试,非常感谢反馈:)

标签: javascript ember.js ember-data


【解决方案1】:

我遇到了同样的问题,我欺骗了寻找“解决方案”

我创建了一个组件“CommentLoader”。该组件采用一个参数 ( post_id ) 和 在“插入”(willInsertElement)之前,我对所有 cmets 进行分级并渲染它们。它有效,但......我并不为此感到自豪:(

【讨论】:

  • “毕业所有 cmets”是什么意思?您在 willInsertElement 中发出自定义 ajax 请求,例如 $.ajax('/cmets?post_id=42') ?
  • 我的意思是抓取:我使用了 queryparmas ( this.store.find('comment', { post_id: params.post_id })
  • 好的,这应该可以,但不幸的是它不关心“链接”的东西。感谢您为此付出一些时间。我想我会接受@marcio-rodrigues-correa-junior 的回答。
【解决方案2】:

更新

就像@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/

【讨论】:

  • 这真的很有趣,我认为它现在可以完成这项工作:) 虽然有一条评论,但我觉得必须给出属性名称很奇怪,因为函数本身位于相应的 manyarray 上。我认为可以通过对 many 数组的一些反思来检索它吗?
  • 我没有找到办法。创建 many 数组时here,我们有类型和所有者,但没有属性名称,我们需要属性名称。在您的情况下,因为帖子与评论只有一种关系,也许可以确定这种关系。在模型有两个相同类型的关系的其他情况下,如何知道当前是什么?看看那个注释代码jsfiddle.net/marciojunior/E2Auc
  • 似乎 ManyArray 有一个属性“名称”,这正是您要寻找的。或者也许我错过了一些东西。见jsfiddle.net/mVxzn/2
  • 惊奇!你是对的,这个属性是设置here,但在class declaration 中不存在所以我认为它不存在:) 我会更新答案。
  • 不错的修复,但我需要在此修复中添加一行额外的代码。在store.findHasMany 上方仅一行,我添加了:meta.type = type;。我目前正在使用 Ember Data 1.0.0-beta.8。
【解决方案3】:

另一种选择是向模型添加方法。也应该适用于 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

【讨论】:

    【解决方案4】:

    重新加载 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
        });
      }
    });
    

    我承认它不是非常漂亮,但这是我想出的最好的解决方案,直到重新加载直接内置到关联中。

    【讨论】:

      【解决方案5】:

      对于 ember-data-1.0.0-beta.10,我正在使用以下模型扩展。

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

      这适用于普通和链接的 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)。

      【讨论】:

        【解决方案6】:

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

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

        您可以通过阅读tests查看一些用例

        【讨论】:

          猜你喜欢
          • 2014-07-06
          • 1970-01-01
          • 1970-01-01
          • 2016-06-13
          • 2020-01-18
          • 1970-01-01
          • 2020-07-31
          • 1970-01-01
          • 2016-10-25
          相关资源
          最近更新 更多