[英]Ember.js/Ember Data takes several minutes to update hasMany of parent after creating thousands of child records
I'm new to Ember.js and running into performance issues when trying to create thousands of records (5300 to be exact) and updating a hasMany relationship. 我是Ember.js的新手,在尝试创建数千条记录(确切地说是5300)并更新hasMany关系时会遇到性能问题。 I'm making a request to my API to retrieve records before I create my new records.
在创建新记录之前,我正在向API请求检索记录。 After the promise returns, I then do a forEach over each record brought down (5300) to do my calculations for the new set of records.
在承诺返回之后,我然后对每个记录下来的记录(5300)执行forEach以对新记录集进行计算。 Creating the records themselves takes about 2 seconds.
创建记录本身大约需要2秒钟。 Updating the hasMany starts off quickly only for the first 40 or so records and then slows to about one update per second.
更新hasMany仅对前40个左右的记录快速启动,然后减慢到每秒约一个更新。
I should also note that this is being done within a component. 我还应该注意到,这是在一个组件内完成的。 I know this is typically anit-pattern, but in this case there is no reason to change the URL or transition.
我知道这通常是anit-pattern,但在这种情况下,没有理由更改URL或转换。 This is a screen where users can select from a pool of items (provided by the route), apply a pricing rule, and then create an event (created in the route) based on those items.
这是一个屏幕,用户可以从一个项目池(由路径提供)中进行选择,应用定价规则,然后根据这些项目创建一个事件(在路径中创建)。 It's a sandbox to determine what items will be a part of the event.
这是一个沙箱,用于确定哪些项目将成为活动的一部分。 Once the users have decided on their items for the event, I then send an action up to the route to perform the actual save and persist to my backend.
一旦用户决定了他们的活动项目,我就会向该路线发送一个动作来执行实际的保存并持续到我的后端。 Outside of the anti-pattern aspect, I can't see how this would affect the performance of the hasMany update.
在反模式方面之外,我无法看到这将如何影响hasMany更新的性能。
I'm using RESTAdapter and RESTSerializer for what it's worth, but that should not have any impact here since I'm just dealing with the Ember data store. 我正在使用RESTAdapter和RESTSerializer来获取它的价值,但这不应该对我有任何影响,因为我只是处理Ember数据存储。
Ember Version: 灰烬版:
Ember : 2.5.1
Ember Data : 2.5.3
jQuery : 2.2.3
Ember Simple Auth : 1.1.0
The two models in question are as follows... 有问题的两个模型如下......
Child Model (event-item): 儿童模特(事件项目):
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')
});
Parent Model (event): 父模型(事件):
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})
});
Event create record: 活动创建记录:
model() {
return this.store.createRecord('event', {});
},
Code block in component responsible for creating records and updating hasMany: 负责创建记录和更新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');
});
So far I've tried the following... 到目前为止,我已尝试过以下内容......
Ember.A()
and then trying to push the new records to the hasMany like so: this.get('event').get('eventItems').pushObjects(newEventItems);
Ember.A()
,然后尝试将新记录推送到hasMany,如下所示: this.get('event').get('eventItems').pushObjects(newEventItems);
. this.get('event').get('eventItems').addObjects(newEventItems);
this.get('event').get('eventItems').addObjects(newEventItems);
. I would assume (and please correct me if I'm wrong) that creating records and updating relationships strictly on the client side should be able to handle thousands of records without too much issue. 我认为(如果我错了请纠正我),严格在客户端创建记录和更新关系应该能够处理数千条记录而不会出现太多问题。 I'm hoping I'm just doing something incorrect or in an inefficient way that will be obvious to someone with more experience.
我希望我只是做一些不正确的事情,或者以一种效率低下的方式对那些经验丰富的人来说是显而易见的。 Any help, including alternatives, is greatly appreciated!
任何帮助,包括替代品,非常感谢!
I've found working with large sets of 'hasMany' relationships to be slow as well. 我发现使用大量'hasMany'关系也很慢。
My advice: Build the relationship on the server with a custom endpoint, and communicate the changes back to the client over websockets. 我的建议:使用自定义端点在服务器上构建关系,并通过websockets将更改传回客户端。 Trying to individually save 5300 records in Ember will make 5300 network requests, whereas this could be accomplished in 1 outbound request, and possibly one websockets message, though it might be advisable to batch the responses in smaller sets.
尝试在Ember中单独保存5300条记录将产生5300个网络请求,而这可以在1个出站请求中完成,可能还有一个websockets消息,尽管建议将响应批量处理为较小的集合。
No need to make the relationships in Ember until the changes are committed. 在更改提交之前,无需在Ember中建立关系。 The returned websockets message should include the relationship's foreign keys Ember Data needs to construct the relationships.
返回的websockets消息应该包含关系的外键Ember Data需要构建关系。
This means that up front, you'll be creating eventItems
(or whatever your model is called) without a parent. 这意味着,在没有父级的情况下,您将创建
eventItems
(或任何模型被调用)。
Finally, you might consider creating the child records on demand, instead of trying to create every child item for the user right away. 最后,您可以考虑按需创建子记录,而不是尝试立即为用户创建每个子项。 Just do the
createRecord
when a user decides to select the item from the pool of items. 当用户决定从项目池中选择项目时,只需执行
createRecord
。 (Hopefully I'm understanding your use case correctly.) If you take that approach, you might not even need to use a custom endpoint as I've described. (希望我能正确理解你的用例。)如果采用这种方法,你甚至可能根本不需要使用我所描述的自定义端点。
Last bit of advice: Your note about 'anti-patterns' is correct: NEVER do CRUD operations, or anything really async, in components, especially not for 5300 items . 最后一点建议:你关于'反模式'的说明是正确的:永远不要在组件中进行CRUD操作或任何真正的异步操作, 特别是对于5300项 。 Components can easily be torn down before an async operation completes, leaving your application in a weird state, and most likely resulting in bugs.
在异步操作完成之前,可以轻松地拆除组件,使应用程序处于奇怪的状态,并且很可能导致错误。 Move whatever you do into the route, like you said, and stick with that pattern.
像你说的那样将你做的任何事情移动到路线中,并坚持使用那种模式。 Components should just be "dumb" templates that display stuff and send actions.
组件应该只是“哑”模板,显示东西和发送动作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.