Main vintage composition Slow composite performances (200+ collections)
When displaying a combined collection with a dropdown of about 200 countries, my application is getting too slow.
What is the best way to improve performance when working with large collections in composite views on a puppet?
Here is a function in the controller that loads very slowly. It runs quickly, removing only the following lines:
@layout.shippingCountryRegion.show shippingCountryView
@layout.billingCountryRegion.show billingCountryView
So it looks very slow.
Show.Controller =
showProfile: ->
@layout = @getLayoutView()
@layout.on "show", =>
headerView = @getHeaderView()
@layout.headerRegion.show headerView
accessView = @getAccessView()
@layout.accessRegion.show accessView
billingReadmeView = @getBillingReadmeView()
@layout.billingReadmeRegion.show billingReadmeView
billingFieldsView = @getBillingFieldsView()
@layout.billingFieldRegion.show billingFieldsView
shippingReadmeView = @getShippingReadmeView()
@layout.shippingReadmeRegion.show shippingReadmeView
shippingFieldsView = @getShippingFieldsView()
@layout.shippingFieldRegion.show shippingFieldsView
MyApp.request "location:get_countries", (countries) =>
billingCountryView = @getBillingCountryView(countries)
@layout.billingCountryRegion.show billingCountryView
MyApp.request "location:get_states", MyApp.activeCustomer.get('billing_country_id'), (states) =>
billingStateView = @getBillingStatesView(states)
@layout.billingStateRegion.show billingStateView
MyApp.request "location:get_countries", (countries) =>
shippingCountryView = @getShippingCountryView(countries)
@layout.shippingCountryRegion.show shippingCountryView
MyApp.request "location:get_states", MyApp.activeCustomer.get('shipping_country_id'), (states) =>
shippingStateView = @getShippingStatesView(states)
@layout.shippingStateRegion.show shippingStateView
MyApp.mainRegion.show @layout
Billing country view:
class View.BillingCountryDropdownItem extends MyApp.Views.ItemView
template: billingCountryItemTpl
tagName: "option"
onRender: ->
this.$el.attr('value', this.model.get('id'));
if MyApp.activeCustomer.get('billing_country_id') == this.model.get('id')
this.$el.attr('selected', 'selected');
class View.BillingCountryDropdown extends MyApp.Views.CompositeView
template: billingCountryTpl
itemView: View.BillingCountryDropdownItem
itemViewContainer: "select"
Template, simply:
<label>Country
<select id="billing_country_id" name="billing_country_id">
<%- name %>
</select>
</label>
A quick solution is required. Thank.
source to share
Your code can be optimized. Just move the content of the method onRender
to attributes ItemView
.
class View.BillingCountryDropdownItem extends MyApp.Views.ItemView
template: billingCountryItemTpl
tagName: "option"
attributes: ->
var id = this.model.get('id');
var attributes = { 'value': id };
if MyApp.activeCustomer.get('billing_country_id') == this.model.get('id')
attributes['selected'] = 'selected';
return attributes
The difference between this method and the tag onRender
is that when rendering will be done when the collection is already done, and more than 200 operations will be performed on DOM nodes, which will lead to performance problems.
In the case of a method, attributes
it is executed when the view is created.
source to share
There are some tips you can follow:
1) Ask yourself, do you really need to display all items at the same time? Perhaps you can display part of the collection and display other items in a scroll, or use pagination or use "virtual scrioll" with SlickGrid or Webix .
2) Check how often you revisit your submission. Try to reduce the number of events that caused re-rendering
3) Try to reduce the number of listeners for ItemView events. Its a good practice for delegating context events to a CollectionView
4) You can use setTimeout
to render the collection piece by piece. For example, you divide you into 4 parts by 50 items and increase the 4 timeouts for rendering.
5) You can optimize the underscore pattern and get rid of the operator with {}
. http://underscorejs.org/#template
source to share
What's in your billingCountryItemTpl variable? If it's just a string with a template ID, you can precompile your template using Marionette.TemplateCache .
So, you will have:
template: Marionette.TemplateCache.get(billingCountryItemTpl)
source to share