Skip to content

Instantly share code, notes, and snippets.

@dirkraft
Last active August 29, 2015 14:08
Show Gist options
  • Save dirkraft/e8c1586232f00bd9bda8 to your computer and use it in GitHub Desktop.
Save dirkraft/e8c1586232f00bd9bda8 to your computer and use it in GitHub Desktop.
Angular $timeout delayed function, limiting invocations of any function, such as a typeahead-like search form input.
/**
* Usage:
* <pre>
* $scope.refresh = new DelayedSearch({
* immediate: function() {
* // always do this immediately
* // e.g. show refreshing indicator
* },
* delayMs: 200,
* delayed: function() {
* // only do this after the required delay. If this DelayedSearch is invoked multiple times
* // within the delay, then only one invocation of 'delayed' will result after the delay.
* // e.g. make actual request to back-end
* }
* });
*
* // Trigger twice in quick succession. This might actually be triggered by changes on a form input.
* $scope.refresh();
* $scope.refresh();
* </pre>
* This example, since invocations of the DelayedSearch happen sequentially and immediately, will invoke the
* 'immediate' function twice, but the 'delayed' function only once after 'delayMs'.
*
* @param config {Object} configuring the DelayedSearch instance
* @param [config.immediate] {function} immediate logic
* @param config.delayed {function} logic that should only be executed beyond the delay barrier
* @param config.delayMs {number} duration of delay before executing the delayedFn
*
* @return {function} that on invocation always evaluates 'immediateFn', and sets a $timeout on
* 'delayedFn'. If this DelayedSearch is invoked again before the delay elapses, then any
* existing $timeout is cancelled before setting up a new timeout on the 'delayedFn'.
*
* @constructor
*/
angular.module('jdunkDelayedAction', []).factory('DelayedAction', ['$timeout', function ($timeout) {
return function (config) {
var currentTimeout = null;
return function () {
// Hold onto current arguments for the delayed function.
var args = arguments;
config.immediate && config.immediate.apply(this, args);
// Cancel any prior accumulating timeout.
if (currentTimeout) {
$timeout.cancel(currentTimeout);
}
currentTimeout = $timeout(function () {
config.delayed.apply(this, args);
}, config.delayMs);
};
}
}]);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment