index.mjs 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. const DEBOUNCE_DEFAULTS = {
  2. trailing: true
  3. };
  4. function debounce(fn, wait = 25, options = {}) {
  5. options = { ...DEBOUNCE_DEFAULTS, ...options };
  6. if (!Number.isFinite(wait)) {
  7. throw new TypeError("Expected `wait` to be a finite number");
  8. }
  9. let leadingValue;
  10. let timeout;
  11. let resolveList = [];
  12. let currentPromise;
  13. let trailingArgs;
  14. const applyFn = (_this, args) => {
  15. currentPromise = _applyPromised(fn, _this, args);
  16. currentPromise.finally(() => {
  17. currentPromise = null;
  18. if (options.trailing && trailingArgs && !timeout) {
  19. const promise = applyFn(_this, trailingArgs);
  20. trailingArgs = null;
  21. return promise;
  22. }
  23. });
  24. return currentPromise;
  25. };
  26. return function(...args) {
  27. if (currentPromise) {
  28. if (options.trailing) {
  29. trailingArgs = args;
  30. }
  31. return currentPromise;
  32. }
  33. return new Promise((resolve) => {
  34. const shouldCallNow = !timeout && options.leading;
  35. clearTimeout(timeout);
  36. timeout = setTimeout(() => {
  37. timeout = null;
  38. const promise = options.leading ? leadingValue : applyFn(this, args);
  39. for (const _resolve of resolveList) {
  40. _resolve(promise);
  41. }
  42. resolveList = [];
  43. }, wait);
  44. if (shouldCallNow) {
  45. leadingValue = applyFn(this, args);
  46. resolve(leadingValue);
  47. } else {
  48. resolveList.push(resolve);
  49. }
  50. });
  51. };
  52. }
  53. async function _applyPromised(fn, _this, args) {
  54. return await fn.apply(_this, args);
  55. }
  56. export { debounce };