Skip to content

Instantly share code, notes, and snippets.

@thgreasi
Last active August 19, 2018 23:13
Show Gist options
  • Save thgreasi/92066623e0fc9afbe6f6e1bc2cd7552b to your computer and use it in GitHub Desktop.
Save thgreasi/92066623e0fc9afbe6f6e1bc2cd7552b to your computer and use it in GitHub Desktop.
[Moved to https://github.com/thgreasi/debounce-with-result.js] An improved version of debounce that returns a Promise and can handle return values. Returns a single Promise for each separate group of debounced invocations.
function debounceWithResult (func, wait, immediate) {
function newDeferred () {
var deferred = {};
deferred.promise = new Promise(function (resolve, reject) {
deferred.resolve = resolve;
deferred.reject = reject;
});
return deferred;
}
var timeout;
var laterDeferred;
return function () {
var context = this, args = arguments;
var later = function () {
timeout = null;
laterDeferred = null;
if (!immediate) {
try {
later.deferred.resolve(func.apply(context, args));
} catch (e) {
later.deferred.reject(e);
}
}
};
later.deferred = laterDeferred = laterDeferred || newDeferred();
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) {
laterDeferred = null;
var deferred = newDeferred();
try {
deferred.resolve(func.apply(context, args));
} catch (e) {
deferred.reject(e);
}
return deferred.promise;
}
return laterDeferred.promise;
};
}
export function debounceWithResult<T> (func: Function, wait?: Number, immediate?: boolean): () => Promise<T> {
interface Deferred<T> {
promise: Promise<T>;
resolve: (value: T) => void;
reject: (error?: any) => void;
}
interface LaterFn<T> extends IHaveDeferred<T> {
(): void;
}
interface IHaveDeferred<T> {
deferred?: Deferred<T>;
}
function newDeferred (): Deferred<T> {
var deferred = {
promise: null,
resolve: null,
reject: null
};
deferred.promise = new Promise(function (resolve, reject) {
deferred.resolve = resolve;
deferred.reject = reject;
});
return deferred;
}
var timeout;
var laterDeferred;
return function (): Promise<T> {
var context = this, args = arguments;
var later: LaterFn<T> = function () {
timeout = null;
laterDeferred = null;
if (!immediate) {
try {
later.deferred.resolve(func.apply(context, args));
} catch (e) {
later.deferred.reject(e);
}
}
};
later.deferred = laterDeferred = laterDeferred || newDeferred();
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) {
laterDeferred = null;
var deferred = newDeferred();
try {
deferred.resolve(func.apply(context, args));
} catch (e) {
deferred.reject(e);
}
return deferred.promise;
}
return laterDeferred.promise;
};
}
@cvara
Copy link

cvara commented Nov 9, 2016

Neat! 👍

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