Coder Social home page Coder Social logo

throttle-debounce's Introduction

throttle-debounce

Build Status BrowserStack Status Mentioned in Awesome Micro npm Packages

Throttle and debounce functions.

This module is the same as jquery-throttle-debounce (with some differences), but it’s transferred to ES Modules and CommonJS format.

Install

npm install throttle-debounce --save

Usage

throttle

import { throttle } from 'throttle-debounce';

const throttleFunc = throttle(
	1000,
	(num) => {
		console.log('num:', num);
	},
	{ noLeading: false, noTrailing: false }
);

// Can also be used like this, because noLeading and noTrailing are false by default
const throttleFunc = throttle(1000, (num) => {
	console.log('num:', num);
});

throttleFunc(1); // Will execute the callback
throttleFunc(2); // Won’t execute callback
throttleFunc(3); // Won’t execute callback

// Will execute the callback, because noTrailing is false,
// but if we set noTrailing to true, this callback won’t be executed
throttleFunc(4);

setTimeout(() => {
	throttleFunc(10); // Will execute the callback
}, 1200);

// Output
// num: 1
// num: 4
// num: 10

debounce

import { debounce } from 'throttle-debounce';

const debounceFunc = debounce(
	1000,
	(num) => {
		console.log('num:', num);
	},
	{ atBegin: false }
);

// Can also be used like this, because atBegin is false by default
const debounceFunc = debounce(1000, (num) => {
	console.log('num:', num);
});

// Won’t execute the callback, because atBegin is false,
// but if we set atBegin to true, this callback will be executed.
debounceFunc(1);

debounceFunc(2); // Won’t execute callback
debounceFunc(3); // Won’t execute callback

// Will execute the callback,
// but if we set atBegin to true, this callback won’t be executed.
debounceFunc(4);

setTimeout(() => {
	debounceFunc(10); // Will execute the callback
}, 1200);

// Output
// num: 4
// num: 10

Cancelling

Debounce and throttle can both be cancelled by calling the cancel function.

const throttleFunc = throttle(300, () => {
	// Throttled function
});

throttleFunc.cancel();

const debounceFunc = debounce(300, () => {
	// Debounced function
});

debounceFunc.cancel();

The logic that is being throttled or debounced will no longer be called.

To cancel only one upcoming debounced call, you can pass upcomingOnly: true option to cancel function:

const debounceFunc = debounce(300, () => {
	// Debounced function
});

debounceFunc(); // will not be invoked

debounceFunc.cancel({ upcomingOnly: true });

debounceFunc(); // will be invoked

API

throttle(delay, callback, { noLeading, noTrailing, debounceMode })

Returns: Function

Throttle execution of a function. Especially useful for rate limiting execution of handlers on events like resize and scroll.

delay

Type: Number

A zero-or-greater delay in milliseconds. For event callbacks, values around 100 or 250 (or even higher) are most useful.

callback

Type: Function

A function to be executed after delay milliseconds. The this context and all arguments are passed through, as-is, to callback when the throttled-function is executed.

noTrailing

Type: Boolean

Optional, defaults to false. If noTrailing is true, callback will only execute every delay milliseconds while the throttled-function is being called. If noTrailing is false or unspecified, callback will be executed one final time after the last throttled-function call. (After the throttled-function has not been called for delay milliseconds, the internal counter is reset)

noLeading

Type: Boolean

Optional, defaults to false. If noLeading is false, the first throttled-function call will execute callback immediately. If noLeading is true, the first the callback execution will be skipped. It should be noted that callback will never executed if both noLeading = true and noTrailing = true.

debounceMode

Type: Boolean

If debounceMode is true (at begin), schedule clear to execute after delay ms. If debounceMode is false (at end), schedule callback to execute after delay ms.

debounce(delay, callback, { atBegin })

Returns: Function

Debounce execution of a function. Debouncing, unlike throttling, guarantees that a function is only executed a single time, either at the very beginning of a series of calls, or at the very end.

delay

Type: Number

A zero-or-greater delay in milliseconds. For event callbacks, values around 100 or 250 (or even higher) are most useful.

callback

Type: Function

A function to be executed after delay milliseconds. The this context and all arguments are passed through, as-is, to callback when the debounced-function is executed.

atBegin

Type: Boolean

Optional, defaults to false. If atBegin is false or unspecified, callback will only be executed delay milliseconds after the last debounced-function call. If atBegin is true, callback will be executed only at the first debounced-function call. (After the throttled-function has not been called for delay milliseconds, the internal counter is reset).

Differences with original module

  • Dependancy on jQuery is removed, so if you rely on GUIDs set by jQuery, plan accordingly
  • There is no standalone version available, so don’t rely on $.throttle and $.debounce to be available

Browser support

Tested in Chrome 72, Edge 15, Firefox 65 and should work in all modern browsers (support based on Browserslist configuration).

Test

For automated tests, run npm run test:automated (append :watch for watcher support).

License

Original module license: Copyright (c) 2010 "Cowboy" Ben Alman (Dual licensed under the MIT and GPL licenses. http://benalman.com/about/license/)
This module license: MIT © Ivan Nikolić

throttle-debounce's People

Contributors

a-korzun avatar brekk avatar cgnonofr avatar eightypop avatar graphmaxer avatar itboos avatar marc136 avatar nikitaeverywhere avatar niksy avatar ossdev07 avatar plee-nm avatar realityking avatar seiyab avatar stamoern avatar tedwu1027 avatar yuu2lee4 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

throttle-debounce's Issues

Debounce or Throttle not working with TypeScript/React

I'm having trouble getting Debounce to work correctly. Here's what I have so far (not sure if you've used React, but basically the handleChangeQuery function will run when the <TextField/> component is typed into)

  handleChangeQuery = (e: any) => {
    this.setState({ query: e.target.value }); // this is running properly
    debounce(200, false, () => console.log('hello world')); // not console logging
  }

  render() {
    const { query } = this.state;
    return (
      <React.Fragment>
        <TextField
          InputProps={{
            placeholder: 'search for something',
            value: query,
            onChange: this.handleChangeQuery,
          }}
        />
      </React.Fragment>
    );
  }
}

for some reason the debounce function is not running at all despite this line before it running properly. Is there some step I'm missing?

e: FYI, I tried using the typings provided and then shortly after deleted the typings file and instead went with https://www.npmjs.com/package/@types/throttle-debounce.

Feature request: is pending

Context

Use case: using throttle with a larger timeout, one might want to call the function one last time on window unload if a call is pending.

Proposal

add a new function isPending to see if an invocation of the wrapped function is scheduled

No way to cancel

Expected something like this:

debouncedF = debounce(1000, F);
debouncedF();
// after 500 ms
debouncedF.cancel();
// not called

Proposal to add/adopt adaptive sync throttling method

An alternate 'throttleAdaptiveSync' method based on requestAnimationFrame, used to throttle user input event in order to achive more fluent redraw for Canvas / WebGL applications.

Background
Consider the following case:

An interactive webpage contains a range <input> and a 2D <canvas>, when the range slider input event gets triggered, the canvas will be redrawed.

Problem

Since the range input may be triggered frequently (8ms ~ 12 ms interval on my computer), Sometimes it causes laggy if canvas redraw takes long time.

Alternative

  • Fixed-delay throttling can basically solve the problem, but that is not perfect for different computers, different screens or different canvas states (normal and fullscreen).
  • Dynamic-delay throttling can be very complex, as complex as TCP congestion control, such it can be heavy-weight, more overhead.

Solution
I worked out a simple method, as a reference implemention, to achive adaptive sync throttling. see online demo and source code.

License condition

Hello,

I have a question, is it possible to define which version are original module a which are not?
We can't use GPL license in our project and we need to have 100% certainty, that we can license under MIT.
Thank you.

Debounce not working

Why debounce not working?

My code
import React from 'react'
import { BaseTextField } from '../../common/form-fields'
import queryString from 'query-string'
import { debounce } from 'throttle-debounce'

import { staticStyles } from './style'

class SearchPanel extends React.Component {

constructor(props) {
super(props)
const query = queryString.parse(props.location.search)
this.state = { search: query.search || '" }
}

handleSearchChange = e => {
e.preventDefault()
const query = queryString.parse(this.props.location.search)
const search = e.target.value
this.setState({ search })
query.search = search || undefined
query.page = 1
this.props.history.replace({
...this.props.location,
search: queryString.stringify(query)
})
debounce(1000, () => this.props.getList(query))
}

render() {
return (






);
}
}

export default SearchPanel

Can I only comply with the MIT license?

Hello, I wanted to use this software, but I ran into a problem. The license.md file contains MIT and GPL licenses, but the package.json file contains only MIT licenses. Which license should I comply with? Can I only comply with the MIT license?

[Violation] 'setTimeout' handler took <some value>ms

Google Chrome 58 and up do not hide these debug information anymore, and it makes this plugin spew a bunch of messages every time the throttled function takes longer to run. One suggestion would to delegate the handler outside of the setTimeout. using a Promise if available.

If the environment does not offer the implementation, then the error won't matter anyway, and a dumb placeholder can be used, something like

if (!Promise) {
	Promise = {
		resolve: function () {
			return {
				then: function(handler) { handler(); );
			};
		}
	};
}

Then change the exec function like so :

function exec () {
	Promise.resolve().then(function () {
		lastExec = Date.now();
		callback.apply(self, args);
	});
}

Strange behaviour with React useState + debounce

Hello!

I am trying to get debounce to work in my project. In the input's onChange, if it also contains a setState, then the debounce function stops working and instead prints out each key stroke individually. I'm wanting the setState to be there, because the value will come from localStorage, and the useState's value is used elsewhere in my app.

https://codesandbox.io/s/adoring-nova-exxfwf?file=/src/App.js

Any explanation on what is happening and how I can work around it would be much appreciated!

Thanks.

Cant seem to get Throttle working with onClick

Hi there,

Apologies, this may be down to me implementing the package incorrectly, but I dont seem to be able to get throttle to work with an onClick - if I rapidly click the button, the console log is fired multiple times. I have this set up as follows:

//throttled-button.js
const ThrottledButton = (props) => {
  const handleOnClick = () => throttle(1000, true, props.onClick)

  return <button onClick={handleOnClick} {...props}>{props.children}</button>
}


// logout.js
const handleLogout = () => {
  console.log("FIRED")
  logoutUser()
}

 <ThrottledButton onClick={handleLogout} type='button'>Logout</ThrottledButton>

I have also tried this in the following configuration, which also doesnt seem to work:

// logout.js
  const handleLogout = throttle(1000, true, () => {
    console.log("FIRED")
    logoutUser()
  })

 <button onClick={handleLogout} type='button'>Logout</button>

As mentioned, if I rapidly click the buttons in either of these configurations, I see FIRED console logged multiple times.

Throttle + debounce?

Is there a way to have the effect of both throttle and debounce? For example, say I throttle by 100ms and I have a series of calls like this:

  • Call A at 0ms
  • Call B at 25ms
  • Call C at 50ms
  • Call D at 99ms
  • Call E at 125ms
  • Call F at 150ms
  • Call G at 175ms
  • Call H at 199ms

At the 100ms mark I want only call D to be called, and at the 200ms mark I want only call H to be called. Calls before the throttle interval are dropped, but last calls are periodically passed through at the throttle interval unlike debounce which waits until all calls have stopped.

Throttle does not throttle on first call

The following declearation does not do anything if the function is called only once :

const t = throttle(100, () => {
  console.log("OK");
}, { noLeading:true });

t();   // will never output anything

Essentially, I am expecting throttle to call the function at least once every 100 ms (in this case), but the function never gets called.

Using debounce won't work because, if the function is called many times, I want the function to throttle, not be debounced, but I don't want the function to be executed immediately; the first call should be debounced.

The current implementation is in error to me.

async debounce?

Hi, how can I get it work with async await? And with this binding
Can we get like a wrapper with working with promises?
I need it for a search input in a vuejs project

Throttling doesn't work.

I'm 100% sure this is developer error, but I can't figure it out...

I have a simple nodejs setup like this:

const debounce = require('throttle-debounce').debounce;

function createExpensiveThing() {
    console.log("called this thing");
    debounce(50, true, () => {
        console.log("throttled called!");
    });
}

setInterval(createExpensiveThing, 100);

And the output:

$ node --version
v11.6.0
$ node throttle-test.js
called this thing
called this thing
called this thing
called this thing
called this thing
called this thing

At no point does the "throttled called!" message appear in the output. The function never fires. What am I missing here?

Usage example doesn't show well the basic functionality

I believe the usage example on the README needs to be better. Now for throttling the example is as follows:

throttle(300, () => {
    // Throttled function
});

One would assume that those lines alone would execute what's there at the // Throttled function. This, however, yet doesn't execute anything. The throttle() call here just returns the throttled function, but in the example it's just lost as it isn't assigned anywhere, so it's not even a working example. The example just doesn't convey the fact that the // Throttled function means that the throttle() is returning a throttled function, not executing it throttled, as the comment is there inside the inner function.

After understanding it, it's quite easy to see why it's working that way, but it isn't intuitive or easy at all to get when you first see the documentation.

To my understanding, the correct usage and a better annotated example would be:

const throttledFunction = throttle(300, () => {
    // The stuff that is expensive to execute
});

throttledFunction(); // Call as often as you like; the inner function is executed only every 300ms

Or something along those lines. And something similar, of course, for debouncing as well.

I believe this lack of a working minimal example is, e.g., a reason why the issue #16 was filed in the first place, as the code provided uses the debounce() in the same way that the function it's returning is just lost, as it's not assigned anywhere.

doesn't work in react native

store.subscribe(() => throttle(1000, () => other.saveState()));

other.saveState is not calling at all, while throttle is called many times

Feature request: Add noLeading option

Context

I currently use the throttle() function in an online form that autosaves the contents of <input> fields when they change. As a user types their text in the form, the throttled save() method is called once every five seconds.

In this scenario, the leading call to the throttled function simply saves the first character that was typed, which is not very useful. Nothing breaks because of it, but it's also a call that does not need to be made in my use-case.

Proposal

Lodash has a boolean leading option that allows skipping the first invocation to the throttled function. I propose adding the same thing to this package.

Typescript typings do not work properly

The typings that were added in 2.0 now can cause compiler errors in typescript projects.

throttle(300, function () {
    // Throttled function
}); 

TS2345: Argument of type '() => void' is not assignable to parameter of type 'boolean'.

How can I get `value` in `react`?

import { debounce } from 'throttle-debounce'

class App extends Component {

  handleChangeValue: debounce(1e3, e=> {
    // How to get the envent value at
  })

  render() {
    return (
      <>
       <input onChange={ this.handleChangeValue } />
      </>
    )
  }
}

How to get the envent value at?

Thank you. I don't know how to do it now, but I know there should be a few solutions🌚

The cancel() method prevents all future invocations

The docs and comments imply this is might not by design, but if it is intended then perhaps the readme can be clarified.

Documentation makes this a little unclear...

The logic that is being throttled or debounced will no longer be called.

The comment in the source code implies only the timeout is being canceled..

Function to cancel next exec

Thanks!

Dual license of MIT/GPL

Hi, I saw in the license file that this module license is dual license under MIT and GPL. I just want to confirm is this module is dual license under BOTH MIT and GPL, or does it dual license under MIT OR GPL, meaning I can select either of them?

Allow injecting a custom setTimeout?

Hardcoding this to always use the global setTimeout is problematic. In most unit testing frameworks, there's no way to programmatically skip forward to the execution time - we'd have to also setTimeout in the tests.

Proposal: allow the methods to take in an object containing the settings, as it's starting to accept quite a few. What if we want to specify noTrailing and setTimeout but not debounceMode?

Normalize debounce API with throttle API changes

When we made changes to throttle API in version 4, incidentally we haven’t aligned those changes to debounce method.

@seiyab are you willing to make same changes to debounce API, along with type changes?

I think it would be great to have similar API for both methods (delay, callback and options).

Getting Error When Running Gulp

I'm getting this error when running gulp.

Error: Cannot find module 'browserify-shim' from '/Users/realph/Desktop/jekyll/node_modules/throttle-debounce'

I'm requiring it, just like the README:

var td = require('throttle-debounce');

Any reason why this is happening?

It is recommended that the change information of API be noted in the README.md file.

I have recently noticed that the API of this plug-in has changed, and it is recommended to add relevant instructions to the README.md file.

Because when I was browsing the code I used throttle-debounce earlier recently, I wanted to know the detailed usage of a parameter in github, only to find that the order of the parameters did not correspond. I went through the history to know that the API had changed.

debounce and throttle seems to decrease performance for window.onscroll

Hi,

Using this package I have done some tests in Firefox and I have noticed using debounce or throttle for window.onscroll function is worse then just allowing the function to run on every pixel scroll.

I wouldnt have thought this because i thought the debounce or throttle would prevent any operations from happening but it seems the operations the debounce/throttle does to debounce operations from happening is more expensive then the operations just happening.

It seems in firefox on every metric says using debounce or throttle for onscroll is worse for performance.
I guess I am putting this here for other developers and for discussion - using throttle and debounce is not always better.

Does anyone have anything to weigh in on this?
I am not a performance measuring pro.

thanks

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.