RotLenin

Untitled

Mar 30th, 2022
668
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. const freeGlobal = typeof global === 'object' && global !== null && global.Object === Object && global
  2.  
  3. /** Detect free variable `globalThis` */
  4. const freeGlobalThis = typeof globalThis === 'object' && globalThis !== null && globalThis.Object == Object && globalThis
  5.  
  6. /** Detect free variable `self`. */
  7. const freeSelf = typeof self === 'object' && self !== null && self.Object === Object && self
  8.  
  9. /** Used as a reference to the global object. */
  10. const root = freeGlobalThis || freeGlobal || freeSelf || Function('return this')()
  11.  
  12. function someCalc(a){
  13.   console.log(a + this.b);
  14. }
  15.  
  16. function isObject(value) {
  17.   const type = typeof value;
  18.   return value != null && (type === 'object' || type === 'function');
  19. }
  20.  
  21. function throttleFn(func, wait, options = {}) {
  22.   let leading = true
  23.   let trailing = true
  24.  
  25.   if (typeof func !== 'function') {
  26.     throw new TypeError('Expected a function')
  27.   }
  28.   if (isObject(options)) {
  29.     leading = 'leading' in options ? !!options.leading : leading
  30.     trailing = 'trailing' in options ? !!options.trailing : trailing
  31.   }
  32.  
  33.   options = Object.assign(options, {
  34.     leading,
  35.     trailing,
  36.     'maxWait': wait
  37.   });
  38.  
  39.   return debounce(func, wait, options)
  40. }
  41.  
  42. function debounce(func, wait, options) {
  43.   let lastArgs,
  44.     lastThis,
  45.     maxWait,
  46.     result,
  47.     timerId,
  48.     lastCallTime
  49.  
  50.   let lastInvokeTime = 0
  51.   let leading = false
  52.   let maxing = false
  53.   let trailing = true
  54.  
  55.   // Bypass `requestAnimationFrame` by explicitly setting `wait=0`.
  56.   const useRAF = (!wait && wait !== 0 && typeof root.requestAnimationFrame === 'function')
  57.  
  58.   if (typeof func !== 'function') {
  59.     throw new TypeError('Expected a function')
  60.   }
  61.   wait = +wait || 0
  62.   if (isObject(options)) {
  63.     leading = !!options.leading
  64.     maxing = 'maxWait' in options
  65.     maxWait = maxing ? Math.max(+options.maxWait || 0, wait) : maxWait
  66.     trailing = 'trailing' in options ? !!options.trailing : trailing
  67.   }
  68.  
  69.   function invokeFunc(time) {
  70.     const args = lastArgs
  71.     const thisArg = lastThis
  72.     lastArgs = lastThis = undefined
  73.     lastInvokeTime = time
  74.     //result = func.apply(thisArg, args)
  75.     result = func.apply(options, args)
  76.     return result
  77.   }
  78.  
  79.   function startTimer(pendingFunc, wait) {
  80.     if (useRAF) {
  81.       root.cancelAnimationFrame(timerId)
  82.       return root.requestAnimationFrame(pendingFunc)
  83.     }
  84.     return setTimeout(pendingFunc, wait)
  85.   }
  86.  
  87.   function cancelTimer(id) {
  88.     if (useRAF) {
  89.       return root.cancelAnimationFrame(id)
  90.     }
  91.     clearTimeout(id)
  92.   }
  93.  
  94.   function leadingEdge(time) {
  95.     // Reset any `maxWait` timer.
  96.     lastInvokeTime = time
  97.     // Start the timer for the trailing edge.
  98.     timerId = startTimer(timerExpired, wait)
  99.     // Invoke the leading edge.
  100.     return leading ? invokeFunc(time) : result
  101.   }
  102.  
  103.   function remainingWait(time) {
  104.     const timeSinceLastCall = time - lastCallTime
  105.     const timeSinceLastInvoke = time - lastInvokeTime
  106.     const timeWaiting = wait - timeSinceLastCall
  107.  
  108.     return maxing
  109.       ? Math.min(timeWaiting, maxWait - timeSinceLastInvoke)
  110.       : timeWaiting
  111.   }
  112.  
  113.   function shouldInvoke(time) {
  114.     const timeSinceLastCall = time - lastCallTime
  115.     const timeSinceLastInvoke = time - lastInvokeTime
  116.  
  117.     // Either this is the first call, activity has stopped and we're at the
  118.     // trailing edge, the system time has gone backwards and we're treating
  119.     // it as the trailing edge, or we've hit the `maxWait` limit.
  120.     return (lastCallTime === undefined || (timeSinceLastCall >= wait) ||
  121.       (timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait))
  122.   }
  123.  
  124.   function timerExpired() {
  125.     const time = Date.now()
  126.     if (shouldInvoke(time)) {
  127.       return trailingEdge(time)
  128.     }
  129.     // Restart the timer.
  130.     timerId = startTimer(timerExpired, remainingWait(time))
  131.   }
  132.  
  133.   function trailingEdge(time) {
  134.     timerId = undefined
  135.  
  136.     // Only invoke if we have `lastArgs` which means `func` has been
  137.     // debounced at least once.
  138.     if (trailing && lastArgs) {
  139.       return invokeFunc(time)
  140.     }
  141.     lastArgs = lastThis = undefined
  142.     return result
  143.   }
  144.  
  145.   function cancel() {
  146.     if (timerId !== undefined) {
  147.       cancelTimer(timerId)
  148.     }
  149.     lastInvokeTime = 0
  150.     lastArgs = lastCallTime = lastThis = timerId = undefined
  151.   }
  152.  
  153.   function flush() {
  154.     return timerId === undefined ? result : trailingEdge(Date.now())
  155.   }
  156.  
  157.   function pending() {
  158.     return timerId !== undefined
  159.   }
  160.  
  161.   function debounced(...args) {
  162.     const time = Date.now()
  163.     const isInvoking = shouldInvoke(time)
  164.  
  165.     lastArgs = args
  166.     lastThis = this
  167.     lastCallTime = time
  168.  
  169.     if (isInvoking) {
  170.       if (timerId === undefined) {
  171.         return leadingEdge(lastCallTime)
  172.       }
  173.       if (maxing) {
  174.         // Handle invocations in a tight loop.
  175.         timerId = startTimer(timerExpired, wait)
  176.         return invokeFunc(lastCallTime)
  177.       }
  178.     }
  179.     if (timerId === undefined) {
  180.       timerId = startTimer(timerExpired, wait)
  181.     }
  182.     return result
  183.   }
  184.   debounced.cancel = cancel
  185.   debounced.flush = flush
  186.   debounced.pending = pending
  187.   return debounced
  188. }
  189.  
  190. // затормозить функцию до одного раза в 1000 мс
  191. const throttle = throttleFn(someCalc, 1000, {b: ' call'});
  192. throttle(1); // выведет 1 call
  193. throttle(2); // (тормозим, не прошло 1000 мс)
  194. throttle(3); // (тормозим, не прошло 1000 мс)
  195.  
Advertisement
Add Comment
Please, Sign In to add comment