javascript - Ember.js/Ember 数据在创建数千个子记录后需要几分钟来更新 hasMany of parent

标签 javascript ember.js ember-data

我是 Ember.js 的新手,在尝试创建数千条记录(准确地说是 5300 条)和更新 hasMany 关系时遇到了性能问题。在创建新记录之前,我正在向我的 API 发出检索记录的请求。 promise 返回后,我对每条记录(5300)执行一次 forEach 来计算新记录集。创建记录本身大约需要 2 秒。更新 hasMany 仅对前 40 条左右的记录快速开始,然后减慢到大约每秒一次更新。

我还应该注意到,这是在一个组件中完成的。我知道这通常是反模式,但在这种情况下,没有理由更改 URL 或转换。这是一个屏幕,用户可以在其中从项目池(由路线提供)中进行选择,应用定价规则,然后基于这些项目创建事件(在 route 创建)。它是一个沙盒,用于确定哪些项目将成为事件的一部分。一旦用户决定了他们的事件项目,我就会向路由发送一个 Action 以执行实际的保存并持久化到我的后端。在反模式方面之外,我看不出这将如何影响 hasMany 更新的性能。

我正在使用 RESTAdapter 和 RESTSerializer 来获得它的值(value),但这在这里应该没有任何影响,因为我只是在处理 Ember 数据存储。

Ember 版本:

Ember             : 2.5.1
Ember Data        : 2.5.3
jQuery            : 2.2.3
Ember Simple Auth : 1.1.0

有问题的两个模型如下...

子模型(事件项):
export default DS.Model.extend({
  event: DS.belongsTo('event'),
  itemNumber: DS.attr('string'),
  styleNumber: DS.attr('string'),
  tier: DS.attr('string'),
  eventPrice: DS.attr('number')
});

父模型(事件):
export default DS.Model.extend({
  eventTypeId: DS.attr('string'),
  eventName: DS.attr('string'),
  eventDesc: DS.attr('string'),
  startDate: DS.attr('moment-date'),
  endDate: DS.attr('moment-date'),
  priority: DS.attr('number'),
  statusCode: DS.attr('string'),
  value: DS.attr('number'),
  eventItems: DS.hasMany('event-item', {async:true})
});

事件创建记录:
model() {
    return this.store.createRecord('event', {});
},

组件中负责创建记录和更新 hasMany 的代码块:
this.get('store').query('pricing', {brandCd: '00'}).then(tiers => {
    tiers.forEach(tier => {
        this.get('event').get('eventItems').createRecord({
            styleNumber: tier.get('styleNumber'),
            itemNumber: tier.get('itemNumber'),
            brandCd: '00',
            tier: tier.get('tier'),
            eventPrice: this._calculateEventPrice(tier.get('origPrice'), this.get('event').get('eventTypeId'), this.get('event').get('value')),
        });
    });

    this.get('event').set('needsUpdated', 'Y');
});

到目前为止,我已经尝试了以下...
  • 将反向关系添加到我的 hasMany 和 belongsTo
  • 将所有创建记录添加到 Ember.A()然后尝试将新记录推送到 hasMany,如下所示:this.get('event').get('eventItems').pushObjects(newEventItems); .还尝试使用 this.get('event').get('eventItems').addObjects(newEventItems); .
  • 在正在创建的记录上设置belongsTo,而不是更新父(事件)的hasMany。
  • 我还继续将此逻辑移动到我的 route ,以确保在组件中执行此操作不会出现奇怪的行为。它执行相同的操作。

  • 我会假设(如果我错了,请纠正我)严格在客户端创建记录和更新关系应该能够处理数千条记录而不会出现太多问题。我希望我只是在做一些不正确或效率低下的事情,这对于有更多经验的人来说是显而易见的。非常感谢任何帮助,包括替代方案!

    最佳答案

    我发现处理大量“hasMany”关系也很慢。

    我的建议:使用自定义端点在服务器上建立关系,并通过 websockets 将更改传达回客户端。尝试在 Ember 中单独保存 5300 条记录将发出 5300 个网络请求,而这可以通过 1 个出站请求和可能的一个 websockets 消息来完成,尽管建议将响应分批成较小的集合。

    在提交更改之前,无需在 Ember 中建立关系。返回的 websockets 消息应该包含关系的外键 Ember Data 需要构建关系。

    这意味着在前面,您将创建 eventItems (或任何你的模型被称为)没有 parent 。

    最后,您可以考虑按需创建子记录,而不是尝试立即为用户创建每个子项。只需执行 createRecord当用户决定从项目池中选择项目时。 (希望我正确理解了您的用例。)如果您采用这种方法,您甚至可能不需要使用我所描述的自定义端点。

    最后一点建议:您关于“反模式”的注释是正确的:永远不要在组件中执行 CRUD 操作或任何真正异步的操作,尤其是对于 5300 件 .在异步操作完成之前,组件很容易被拆除,使您的应用程序处于奇怪的状态,并且很可能导致错误。如您所说,将您所做的任何事情都移到 route ,并坚持该模式。组件应该只是显示内容和发送操作的“愚蠢”模板。

    关于javascript - Ember.js/Ember 数据在创建数千个子记录后需要几分钟来更新 hasMany of parent,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37492446/

    相关文章:

    javascript - Ember 2,使用 Ember.run.debounce 调用路由中的函数

    transactions - Ember-data:如何在 Controller 操作之间的事务中共享和更新对象?

    javascript - 移动菜单链接无效

    javascript - 如何使用 react 在图像中的对象上绘制矩形?

    javascript - Emberjs 事件 vs 观察者

    Ember.js:一种实现真正全能路线的方法?

    Ember.js "hasMany through"

    ember.js - 如何确定 ember 应用程序的环境

    javascript - D3js 按钮 onclick 函数可缩放特定时间范围内的图表

    javascript - 无法安装 craco