Skip to content

Instantly share code, notes, and snippets.

@gbishop
Created November 2, 2010 14:37
Show Gist options
  • Save gbishop/659693 to your computer and use it in GitHub Desktop.
Save gbishop/659693 to your computer and use it in GitHub Desktop.
A hack at customized callback behavior in dojo
dojo.provide('uow.hitcher');
/*
uow.hitcher: provide additional control over callbacks
usage:
my = uow.hitcher({ callPeriod: 500 }); // note this didn't hitch, it created a hitcher named my.
your = uow.hitcher(); // this one is independent of the first
// use it just like dojo.hitch
dojo.connect(window, 'keydown', my.hitch(this, 'foo'));
dojo.connect(button, 'onClick', my.hitch(bar));
// now foo (and in every case bar) will be called at most every 500 ms, other attempts will be ignored
// later
my.disable();
will prevent calling foo
my.enable();
will allow calling foo
my.set({disableAfterCall: true});
will disable foo after one call.
my.set({callPeriod:200});
will change the preference to call it every 200ms.
my = uow.hitcher({ onError: myCustomErrorReporter });
creates a hitcher with custom error handling.
my = uow.hitcher({ onSkip: mySkipReporter });
creates a hitcher that reports whenever a callback was skipped.
*/
uow.hitcher = function(args) {
// initial values for the arguments including defaults
var init = dojo.mixin({
// limit calls to this often, default=0 which is unlimited
callPeriod: 0,
// disable calling if false, default=true
callEnabled: true,
// disable calling after one call if true, default=false
disableAfterCall: false,
// called whenever the callback throws an exception, default=console.log
onError: console.log,
// called whenever the callback is ignored for any reason, default=null
onSkip: null
}, args);
// current values
var state = dojo.mixin({}, init);
return {
// replacement for dojo.hitch allowing control over if they are called
hitch: function(context, method) {
var f = dojo.hitch(context, method);
var g = function() {
var now = Date.now();
if (!state.callEnabled || state.callPeriod && (now - state.lastCall) < state.callPeriod) {
if (state.onSkip) {
state.onSkip();
}
return;
}
state.lastCall = now;
try {
var result = f.apply(this, arguments || []);
} catch(err) {
if (state.onError) {
state.onError(err);
}
} finally {
if (state.disableAfterCall) {
state.callEnabled = false;
}
}
return result;
};
return g;
},
// set state variables after initialization
set: function(value) {
dojo.mixin(state, value);
},
// enable calling the function
enable: function() {
state.callEnabled = true;
},
// disable calling the function
disable: function() {
state.callEnabled = false;
},
// reset to the initial values
reset: function(value) {
if (value) {
dojo.mixin(init, value);
}
dojo.mixin(state, init);
}
};
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment