Open HAKASHUN opened 10 years ago
やはり、双方向データバインディングはかなりパフォーマンス的に問題あり 本当に必要なときだけ、Angularの便利機能を使うという考え方にたたないと、後で大変だ...
Unfortunately, people seem to treat the $timeout() function in AngularJS as a set-it and forget-it type of function. But, forgetting about your $timeout callback can have negative consequences, all the way from code that fails silently to code that raises an exception to code that makes repeated $http requests to your server for no reason. The trick to managing your $timeout timers properly is to cancel them in your $destroy events.
https://github.com/angular/angular.js/blob/master/src/ng/timeout.js#L35-L59
$timeoutを使うときは、digest loopを意識して、必要なとき以外は、明示的にfalseを渡すか、setTimeoutを用いるべき
上記の第4引数のパラメーターに$rootScope.apply()を行わないためのbooleanを入れることができるが、$rootScope.apply()は避けられても、 $interval内部で行われているdefferで$evalAsyncを読んでるため、結果タイミングはscopeが更新されてしまうっていう・・・w
https://github.com/angular/angular.js/commit/19b6b3433ae9f8523cbc72ae97dbcf0c06960148
But when rendering large DOM trees like containing tables with sort able columns, filtering and stuff ... it might get slower than you want ...
- やはりAngularJSでフィルタとかソート駆使すると重いよね...
The hints detailed in this article can improve AngularJS pages rendering up to 1000% and more - no kidding !
- 1000%もレンダリングはやくするらしい...
If you read the excellent answer over at Stackoverflow: Databinding in angularjs then you might noticed that AngularJS compares the last rendered data with the current datamodel whenever $apply was called to evaluate which parts of the DOM must be updated.
- $applyされるとき現在のデータモデルと最後にレンダリングされるでーたを比べるからいけないみたい
Where are the bottlenecks ?
- If you open the jsFiddle example in a new browser window with opened Javascript console you will see that function getEntries() will be called 2 times. But ist just a single reference to getEntries in the template, correct ? The reason is that AngularJS renders the page and then checks if the rendered data was changed while rendering (Remember, your data model may change while rendering : see ng-init).
- Whenever you type in some data in the label/value INPUT fields AngularJS will again check if the rendered data was changed.
- If you change the item order, AngularJS will again check if the rendered data was changed.
<div ng-repeat="entry in getEntries() | orderBy:order">
getEntries
を書くと、なぜか2回実行されてる...The single point slowing down performance is the repeated call to getEntries() and the orderBy filter. The solution to our problem is simple : We can cache the ordered entries !
- 問題を解決できるらしい...期待。
To not reinvent the wheel we take the exceptional excellent lodash library to help us implement caching. lodash is used to
- order items using _.sortBy instead of the AngularJS orderBy filter
- cache the resulting sorted item list using _.memoize.
- filter使うのをやめて、lodashの
_.memoize
を使おう!ということらしい。_.memoize
の第1引数は、配列を返す関数で、第2引数はcacheKeyを返す関数- リストが変更されたら、キャッシュをクリアすれば問題ないらしい。
サンプルを見る限り、getEntries関数は無駄に複数呼ばれていない! すごい!!!
扱っているプロダクトで、memoizeを使えそうな箇所があったので対応してみたので感想を。
<div ng-repeat="entry in getEntries()">
このように、テンプレートにfunction
を定義すると、memoizeで実装した関数は複数回実行されてしまう。
なので、
<div ng-repeat="entry in entries">
このようにテンプレートに表示したいアイテム配列を渡してあげた方が良い。 しかるべきタイミングで、表示アイテムを変更するときは、コントローラ内で行うようにしたらいい。
http://stackoverflow.com/questions/9682092/databinding-in-angularjs/9693933#9693933
http://daginge.com/technology/2013/08/11/debugging-performance-problems-in-angularjs-with-batarang/