作者:奥兰度
// 一个用来一定时间之后,最后执行传入的函数,// 用来控制一定时间段内,只触发一次传入的函数// 防抖function debounce(fn, time) {let timerreturn function (...args) {if (timer) {clearTimeout(timer)}timer = setTimeout(() => {fn(...args)}, time)}}// 节流function throttle(fn, time) {let timerreturn function (...args) {if (timer) {return}timer = setTimeout(() => {fn(...args)timer = null}, time)}}
作者:xl
function debounce(func, wait) {let timeout;return function() {const context = this;const args = arguments;clearTimeout(timeout);timeout = setTimeout(function() {func.apply(context, args);}, wait);}}function throttle(fn, delay) {let cur = Date.now();return function() {const context = this;const args = arguments;const now = Date.now();if (now - cur >= delay) {cur = Date.now();fn.apply(context, args);}}}
作者:安静
function throttle(fn, delay) {let timer = null;return function () {if (timer) {return;}timer = setTimeout(() => {fn.apply(this, arguments);timer = null;}, delay);};}function debounce(fn, delay) {// 定时器let timer = null;// 将debounce处理结果当作函数返回return function () {// 每次事件被触发时,都去清除之前的旧定时器if (timer) {clearTimeout(timer);}// 设立新定时器timer = setTimeout(() => {fn.apply(this, arguments);}, delay);};}
作者:gochri
let myDebounce = (func, wait = 0, immediately = true, option = { leading: false, maxWait: 0, trailing: true }) => {if (typeof func !== 'function') {throw new Error('Expected a function')}if (typeof wait !== 'number') {throw new Error('wait not a number')}let timeoutID = nullfunction debounced(...args) {if (timeoutID !== null) {clearTimeout(timeoutID);}timeoutID = setTimeout(func, wait);}return debounced}// 测试用例let foo = () => { console.log('foo') }// foo()let debounced = myDebounce(foo, 100)// debounced()for (let i = 0; i < 10; i++) {// setTimeout(() => {debounced()// }, 300);}// foo// 测试用例结束// TODOimport Debounce from 'lodash-decorators/debounce';@debounce(500)function name(params) {}
作者:lodash
import isObject from './isObject.js'import root from './.internal/root.js'/*** Creates a debounced function that delays invoking `func` until after `wait`* milliseconds have elapsed since the last time the debounced function was* invoked, or until the next browser frame is drawn. The debounced function* comes with a `cancel` method to cancel delayed `func` invocations and a* `flush` method to immediately invoke them. Provide `options` to indicate* whether `func` should be invoked on the leading and/or trailing edge of the* `wait` timeout. The `func` is invoked with the last arguments provided to the* debounced function. Subsequent calls to the debounced function return the* result of the last `func` invocation.** **Note:** If `leading` and `trailing` options are `true`, `func` is* invoked on the trailing edge of the timeout only if the debounced function* is invoked more than once during the `wait` timeout.** If `wait` is `0` and `leading` is `false`, `func` invocation is deferred* until the next tick, similar to `setTimeout` with a timeout of `0`.** If `wait` is omitted in an environment with `requestAnimationFrame`, `func`* invocation will be deferred until the next frame is drawn (typically about* 16ms).** See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)* for details over the differences between `debounce` and `throttle`.** @since 0.1.0* @category Function* @param {Function} func The function to debounce.* @param {number} [wait=0]* The number of milliseconds to delay; if omitted, `requestAnimationFrame` is* used (if available).* @param {Object} [options={}] The options object.* @param {boolean} [options.leading=false]* Specify invoking on the leading edge of the timeout.* @param {number} [options.maxWait]* The maximum time `func` is allowed to be delayed before it's invoked.* @param {boolean} [options.trailing=true]* Specify invoking on the trailing edge of the timeout.* @returns {Function} Returns the new debounced function.* @example** // Avoid costly calculations while the window size is in flux.* jQuery(window).on('resize', debounce(calculateLayout, 150))** // Invoke `sendMail` when clicked, debouncing subsequent calls.* jQuery(element).on('click', debounce(sendMail, 300, {* 'leading': true,* 'trailing': false* }))** // Ensure `batchLog` is invoked once after 1 second of debounced calls.* const debounced = debounce(batchLog, 250, { 'maxWait': 1000 })* const source = new EventSource('/stream')* jQuery(source).on('message', debounced)** // Cancel the trailing debounced invocation.* jQuery(window).on('popstate', debounced.cancel)** // Check for pending invocations.* const status = debounced.pending() ? "Pending..." : "Ready"*/function debounce(func, wait, options) {let lastArgs,lastThis,maxWait,result,timerId,lastCallTimelet lastInvokeTime = 0let leading = falselet maxing = falselet trailing = true// Bypass `requestAnimationFrame` by explicitly setting `wait=0`.const useRAF = (!wait && wait !== 0 && typeof root.requestAnimationFrame === 'function')if (typeof func !== 'function') {throw new TypeError('Expected a function')}wait = +wait || 0if (isObject(options)) {leading = !!options.leadingmaxing = 'maxWait' in optionsmaxWait = maxing ? Math.max(+options.maxWait || 0, wait) : maxWaittrailing = 'trailing' in options ? !!options.trailing : trailing}function invokeFunc(time) {const args = lastArgsconst thisArg = lastThislastArgs = lastThis = undefinedlastInvokeTime = timeresult = func.apply(thisArg, args)return result}function startTimer(pendingFunc, wait) {if (useRAF) {root.cancelAnimationFrame(timerId)return root.requestAnimationFrame(pendingFunc)}return setTimeout(pendingFunc, wait)}function cancelTimer(id) {if (useRAF) {return root.cancelAnimationFrame(id)}clearTimeout(id)}function leadingEdge(time) {// Reset any `maxWait` timer.lastInvokeTime = time// Start the timer for the trailing edge.timerId = startTimer(timerExpired, wait)// Invoke the leading edge.return leading ? invokeFunc(time) : result}function remainingWait(time) {const timeSinceLastCall = time - lastCallTimeconst timeSinceLastInvoke = time - lastInvokeTimeconst timeWaiting = wait - timeSinceLastCallreturn maxing? Math.min(timeWaiting, maxWait - timeSinceLastInvoke): timeWaiting}function shouldInvoke(time) {const timeSinceLastCall = time - lastCallTimeconst timeSinceLastInvoke = time - lastInvokeTime// Either this is the first call, activity has stopped and we're at the// trailing edge, the system time has gone backwards and we're treating// it as the trailing edge, or we've hit the `maxWait` limit.return (lastCallTime === undefined || (timeSinceLastCall >= wait) ||(timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait))}function timerExpired() {const time = Date.now()if (shouldInvoke(time)) {return trailingEdge(time)}// Restart the timer.timerId = startTimer(timerExpired, remainingWait(time))}function trailingEdge(time) {timerId = undefined// Only invoke if we have `lastArgs` which means `func` has been// debounced at least once.if (trailing && lastArgs) {return invokeFunc(time)}lastArgs = lastThis = undefinedreturn result}function cancel() {if (timerId !== undefined) {cancelTimer(timerId)}lastInvokeTime = 0lastArgs = lastCallTime = lastThis = timerId = undefined}function flush() {return timerId === undefined ? result : trailingEdge(Date.now())}function pending() {return timerId !== undefined}function debounced(...args) {const time = Date.now()const isInvoking = shouldInvoke(time)lastArgs = argslastThis = thislastCallTime = timeif (isInvoking) {if (timerId === undefined) {return leadingEdge(lastCallTime)}if (maxing) {// Handle invocations in a tight loop.timerId = startTimer(timerExpired, wait)return invokeFunc(lastCallTime)}}if (timerId === undefined) {timerId = startTimer(timerExpired, wait)}return result}debounced.cancel = canceldebounced.flush = flushdebounced.pending = pendingreturn debounced}export default debouncelet fn = debounce(console.log).bind(this)for(let i = 0; i < 10000; i++) {fn(i)}
作者:lodash.throttle
import debounce from './debounce.js'import isObject from './isObject.js'/*** Creates a throttled function that only invokes `func` at most once per* every `wait` milliseconds (or once per browser frame). The throttled function* comes with a `cancel` method to cancel delayed `func` invocations and a* `flush` method to immediately invoke them. Provide `options` to indicate* whether `func` should be invoked on the leading and/or trailing edge of the* `wait` timeout. The `func` is invoked with the last arguments provided to the* throttled function. Subsequent calls to the throttled function return the* result of the last `func` invocation.** **Note:** If `leading` and `trailing` options are `true`, `func` is* invoked on the trailing edge of the timeout only if the throttled function* is invoked more than once during the `wait` timeout.** If `wait` is `0` and `leading` is `false`, `func` invocation is deferred* until the next tick, similar to `setTimeout` with a timeout of `0`.** If `wait` is omitted in an environment with `requestAnimationFrame`, `func`* invocation will be deferred until the next frame is drawn (typically about* 16ms).** See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)* for details over the differences between `throttle` and `debounce`.** @since 0.1.0* @category Function* @param {Function} func The function to throttle.* @param {number} [wait=0]* The number of milliseconds to throttle invocations to; if omitted,* `requestAnimationFrame` is used (if available).* @param {Object} [options={}] The options object.* @param {boolean} [options.leading=true]* Specify invoking on the leading edge of the timeout.* @param {boolean} [options.trailing=true]* Specify invoking on the trailing edge of the timeout.* @returns {Function} Returns the new throttled function.* @example** // Avoid excessively updating the position while scrolling.* jQuery(window).on('scroll', throttle(updatePosition, 100))** // Invoke `renewToken` when the click event is fired, but not more than once every 5 minutes.* const throttled = throttle(renewToken, 300000, { 'trailing': false })* jQuery(element).on('click', throttled)** // Cancel the trailing throttled invocation.* jQuery(window).on('popstate', throttled.cancel)*/function throttle(func, wait, options) {let leading = truelet trailing = trueif (typeof func !== 'function') {throw new TypeError('Expected a function')}if (isObject(options)) {leading = 'leading' in options ? !!options.leading : leadingtrailing = 'trailing' in options ? !!options.trailing : trailing}return debounce(func, wait, {leading,trailing,'maxWait': wait})}export default throttle
