Skip to content

Instantly share code, notes, and snippets.

@WebReflection
Last active March 4, 2020 23:39
Show Gist options
  • Star 10 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save WebReflection/7286687 to your computer and use it in GitHub Desktop.
Save WebReflection/7286687 to your computer and use it in GitHub Desktop.
whenever you need to execute something after an interaction that might happen many times (panning, scrolling, etc) … this simple mechanism makes simple to execute that maybe expensive operations only once when things are "quiet" and never before or in the middle, if an action start as "start panning" would be is fired and it's calling the clear(…
/*jslint browser: true, indent: 2 */
var Delayed = (function (delay) {
/*! Andrea Giammarchi - Mit Style License */
// https://gist.github.com/WebReflection/7286687
'use strict';
// method shared across all delayed wrappers
function clear() {
/*jshint validthis: true */
// Infinity is the "never executed" state
// if fn.clear() is invoke before the execution
// then there is nothing to clear
// same is for already executed state
if (this.waiting !== Infinity || this.waiting !== 0) {
clearTimeout(this.waiting);
}
// if it was waiting, better mark as non waiting anymore
// somebody cleared this delayed state so it's reflected
this.waiting = 0;
}
// method recycled per each setTimeout call
// no need to create extra closures
function invoke(delayed, callback, context, args) {
// mark as consumed already, not waiting anymore
delayed.waiting = 0;
// finally invoke the callback
callback.apply(context, args);
}
// the delayed wrapper exported function
// accepts a callback and optional delay in millisecons
function Delayed(callback, delay) {
// the returned wrapper
function delayed() {
/*jshint validthis: true */
// ensure the right clear method
clear.call(delayed);
// re-set the timeout (will be again in waiting state)
delayed.waiting = setTimeout(
invoke, // the recycled function
delay, // the specific delay to wait for
delayed, // the wrapper to clean up
callback, // the original callback
this, // the current context
arguments // current list of arguments
);
}
// if not specified or 0, the default is used instead
if (!delay) {
delay = Delayed.delay;
}
// exposing a method to stop the execution while waiting
delayed.clear = clear;
// until it's executed first time, the state is waiting
delayed.waiting = Infinity;
// state will be falsy once cleared or executed
return delayed;
}
// the default delay per each wrapper, if not specified
Delayed.delay = delay;
// the exported utility
return Delayed;
}(500));
@WebReflection
Copy link
Author

few examples on how to in calendar.perfplanet.com

If you are targeting IE < 9 browser you might want to use this snippet to normalize setTimeout extra arguments:

/*@cc_on
(function(f){
 window.setTimeout =f(window.setTimeout);
 window.setInterval =f(window.setInterval);
})(function(f){return function(c,t){var a=[].slice.call(arguments,2);return f(function(){c.apply(this,a)},t)}});
@*/

@kentaromiura
Copy link

Apparently jshint get scared by a function referencing this outside an object,
solved by adding /*jshint validthis: true */
after clear() and delayed() method definition,
see https://gist.github.com/kentaromiura/7874867

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment