Reputation: 3130
I have a controller which observes a property (array), and every time it changes, calls an expensive function on the server, then displays the result.
In the initial controller setup (in the route), I need to loop through the array and set some of the values - i.e.
something.forEach(function(el) { myArrayProperty.set(el.id, true); });
This is firing the observer on every loop through the forEach
. How can I loop through the forEach
, update all the elements, and THEN allow the Ember observer to fire?
I've tried scheduleOnce
and Ember.run(function() {..})
but I can't quite seem to get it working.
Thanks!
Upvotes: 2
Views: 332
Reputation: 28587
One way of tackling this problem is to throttle or debounce the expensive function(s) that observe the array.
E.g. you have this now:
App.MyController = Ember.ArrayController.extend({
myExpensiveObserver: function() {
/* some expensive computations */
}.observes('[email protected]'),
});
... and you change that to this instead:
App.MyController = Ember.ArrayController.extend({
myExpensiveObserver: function() {
Ember.run.debounce(this, this.myExpensiveObserverImpl, 300);
}.observes('[email protected]'),
myExpensiveObserverImpl: function() {
/* some expensive computations */
},
});
(replace 300
with the minumum interval you want between recomputations.)
There is a subtle difference between Ember.run.debounce and Ember.run.throttle, and you might prefer one of them over the other. However, from your description, it sounds like either one could fit the bill.
As pointed out by @kingpin2k, be careful with the function you pass in to debounce or throttle. It cannot be anonymous, as Ember will not be able to determine whether they were indeed the same each time it is invoked.
Upvotes: 2
Reputation: 47367
bguiz is totally right, throttle or debounce it. Throttling will allow it to run every x milliseconds, and debounce will block it from running until it hasn't run for x milliseconds. One small nuance that was missed in the other answer is the way Ember keeps track of the debounces/throttles is by the comparing the passed in function. So passing in an anonymous function each time will just keep firing without throttling/debouncing.
App.MyController = Ember.ArrayController.extend({
myExpensiveObserver: function() {
Ember.run.debounce(this, this.realWorker, 300);
}.observes('[email protected]'),
realWorker: function(){
console.log("I'm working");
},
myExpensiveObserverThrottle: function() {
Ember.run.throttle(this, this.realWorkerThrottle, 300);
}.observes('[email protected]'),
realWorkerThrottle: function(){
console.log("I'm working");
}
});
Example: http://emberjs.jsbin.com/cixawagi/1/edit
Upvotes: 1