src/vs/base/common/decorators.ts/throttle
export function throttle<T>(delay: number, reducer?: IDebounceReducer<T>, initialValueProvider?: () => T): Function {
	return createDecorator((fn, key) => {
		const timerKey = `$throttle$timer$${key}`;
		const resultKey = `$throttle$result$${key}`;
		const lastRunKey = `$throttle$lastRun$${key}`;
		const pendingKey = `$throttle$pending$${key}`;

		return function (this: any, ...args: any[]) {
			if (!this[resultKey]) {
				this[resultKey] = initialValueProvider ? initialValueProvider() : undefined;
			}
			if (this[lastRunKey] === null || this[lastRunKey] === undefined) {
				this[lastRunKey] = -Number.MAX_VALUE;
			}

			if (reducer) {
				this[resultKey] = reducer(this[resultKey], ...args);
			}

			if (this[pendingKey]) {
				return;
			}

			const nextTime = this[lastRunKey] + delay;
			if (nextTime <= Date.now()) {
				this[lastRunKey] = Date.now();
				fn.apply(this, [this[resultKey]]);
				this[resultKey] = initialValueProvider ? initialValueProvider() : undefined;
			} else {
				this[pendingKey] = true;
				this[timerKey] = setTimeout(() => {
					this[pendingKey] = false;
					this[lastRunKey] = Date.now();
					fn.apply(this, [this[resultKey]]);
					this[resultKey] = initialValueProvider ? initialValueProvider() : undefined;
				}, nextTime - Date.now());
			}
		};
	});
}