在创建数千个子记录后,Ember.js/Ember Data需要几分钟才能更新hasMany的父级

Set*_*h T 6 javascript ember.js ember-data

我是Ember.js的新手,在尝试创建数千条记录(确切地说是5300)并更新hasMany关系时遇到性能问题.在创建新记录之前,我正在向API请求检索记录.在承诺返回之后,我然后对每个记录下来的记录(5300)执行forEach以对新记录集进行计算.创建记录本身大约需要2秒钟.更新hasMany仅对前40个左右的记录快速启动,然后减慢到每秒约一个更新.

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

我正在使用RESTAdapter和RESTSerializer来获取它的价值,但这不应该对我有任何影响,因为我只是处理Ember数据存储.

灰烬版:

Ember             : 2.5.1
Ember Data        : 2.5.3
jQuery            : 2.2.3
Ember Simple Auth : 1.1.0
Run Code Online (Sandbox Code Playgroud)

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

儿童模特(事件项目):

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')
});
Run Code Online (Sandbox Code Playgroud)

父模型(事件):

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})
});
Run Code Online (Sandbox Code Playgroud)

活动创建记录:

model() {
    return this.store.createRecord('event', {});
},
Run Code Online (Sandbox Code Playgroud)

负责创建记录和更新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');
});
Run Code Online (Sandbox Code Playgroud)

到目前为止,我已尝试过以下内容......

  • 添加与我的hasMany和belongsTo的反向关系
  • 将所有创建记录添加到a Ember.A()然后尝试将新记录推送到hasMany,如下所示:this.get('event').get('eventItems').pushObjects(newEventItems);.也尝试使用它this.get('event').get('eventItems').addObjects(newEventItems);.
  • 在正在创建的记录上设置belongsTo,而不是更新父(事件)的hasMany.
  • 我也继续前进并将这个逻辑移到我的路线中,以确保我在组件中执行此操作时没有得到奇怪的行为.它执行相同的操作.

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

Tim*_*Tim 0

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

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

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

这意味着您将在没有父级的情况下创建eventItems(或无论您的模型被称为什么)。

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

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