| 'use strict'; |
|
|
| const DEBOUNCE_DEFAULTS = { |
| trailing: true |
| }; |
| function debounce(fn, wait = 25, options = {}) { |
| options = { ...DEBOUNCE_DEFAULTS, ...options }; |
| if (!Number.isFinite(wait)) { |
| throw new TypeError("Expected `wait` to be a finite number"); |
| } |
| let leadingValue; |
| let timeout; |
| let resolveList = []; |
| let currentPromise; |
| let trailingArgs; |
| const applyFn = (_this, args) => { |
| currentPromise = _applyPromised(fn, _this, args); |
| currentPromise.finally(() => { |
| currentPromise = null; |
| if (options.trailing && trailingArgs && !timeout) { |
| const promise = applyFn(_this, trailingArgs); |
| trailingArgs = null; |
| return promise; |
| } |
| }); |
| return currentPromise; |
| }; |
| return function(...args) { |
| if (currentPromise) { |
| if (options.trailing) { |
| trailingArgs = args; |
| } |
| return currentPromise; |
| } |
| return new Promise((resolve) => { |
| const shouldCallNow = !timeout && options.leading; |
| clearTimeout(timeout); |
| timeout = setTimeout(() => { |
| timeout = null; |
| const promise = options.leading ? leadingValue : applyFn(this, args); |
| for (const _resolve of resolveList) { |
| _resolve(promise); |
| } |
| resolveList = []; |
| }, wait); |
| if (shouldCallNow) { |
| leadingValue = applyFn(this, args); |
| resolve(leadingValue); |
| } else { |
| resolveList.push(resolve); |
| } |
| }); |
| }; |
| } |
| async function _applyPromised(fn, _this, args) { |
| return await fn.apply(_this, args); |
| } |
|
|
| exports.debounce = debounce; |
|
|