Recent React.JS Conf had Flux panel and Kyle Davis mentioned de-bounce calls based on dispatch loop optimization. Can anyone provide some examples on how to implement that?
My understanding is that it looks something like this:
function debounce(duration) {
var _timer = null;
var toCall = [];
function dispatch() {
_timer = null;
toCall.forEach(function(opts) {
if (opts.shouldCall) {
opts.fn.apply(undefined, opts.args);
}
opts.shouldCall = false;
});
}
return function debounce(fn) {
var myAction = {fn: fn, args: [], shouldCall: false};
toCall.push(myAction);
return function() {
myAction.shouldCall = true;
myAction.args = Array.prototype.slice.call(arguments);
clearTimeout(_timer);
_timer = setTimeout(dispatch, duration);
};
};
}
This looks quite complicated, but all it really is is a trailing-only shared debounce. Multiple functions are debounced on the same timer, and all are called in the same tick. The most recent arguments are preserved (not needed in this specific case, but it's not going to cause problems).
We create one of these for all (not each) of our stores. The duration is mostly arbitrary, but is long enough to allow the browser to render a frame between us doing our store update logic, and the UI updating which may make scrolling feel more responsive.
var storeDebounce = debouncer(20);
In our stores, instead of this:
emitChange: function() {
this.emit(CHANGE_EVENT);
},
We do this:
emitChange: storeDebounce(function() {
this.emit(CHANGE_EVENT);
}.bind(this)),
Now if a store or stores are updated multiple times in the same tick, or short succession (often happens with promises or other guaranteed asynchronous code), we'll only emit a single change event for each affected store.
disclaimer: not tested