Coder Social home page Coder Social logo

mini-throttle's Introduction

mini-throttle

This is a package which provides throttle and debounce functions, with both flow and TypeScript declarations, and a minimal code footprint (less than 60 lines, less than 350 bytes minified+gzipped)

throttling, debouncing, and everything inbetween

type ThrottleOptions = {
  start?: boolean, // fire immediately on the first call
  middle?: boolean, // if true, fire as soon as `wait` has passed
  once?: boolean, // cancel after the first successful call
}
function throttle<T>(
  callback: (...args: T[]) => any,
  wait: number,
  opts?: ThrottleOptions
): (...args: T[]) => void

function debounce<T>(
  callback: (...args: T[]) => any,
  wait: number,
  opts?: ThrottleOptions
): (...args: T[]) => void

This package comes with two functions; throttle and debounce.

Both of these functions offer the exact same signature, because they're both the same function - just with different opts defaults:

  • throttle opts default to { start: true, middle: true, once: false }.
  • debounce opts default to { start: false, middle: false, once: false }.

Each of the options changes when callback gets called. The best way to illustrate this is with a marble diagram.

for (let i = 1; i <= 10; ++i) {
  fn(i)
  await delay(50)
}
await delay(100)
| fn()                                         | 1 2 3 4 5 6 7 8 9 10 |
| throttle(fn, 100)                            | 1 2   4   6   8   10 |
| throttle(fn, 100, {start: false})            |   2   4   6   8   10 |
| throttle(fn, 100, {middle: false})           | 1                 10 |
| throttle(fn, 100, {once: true})              | 1                    |
| throttle(fn, 100, {once: true, start: false})|   2                  |
| debounce(fn, 100)                            |                   10 |

TypeScript Decorators Support!

This package also includes a decorator module which can be used to provide TypeScript Decorator annotations to functions.

Here's an example, showing what you need to do:

import {throttle} from '@github/mini-throttle/decorators'
//                                           ^ note: add `/decorators` to the import to get decorators

class MyClass {
  @throttle(100, { start: false }) // <- Just like normal throttle, but you omit the callback argument
  doThings() {
    // `MyClass.prototype.doThings` will be throttled!
  }
}

mini-throttle's People

Contributors

38elements avatar dependabot[bot] avatar dgraham avatar dgreif avatar hoishin avatar keithamus avatar koddsson avatar manuelpuyol avatar percy507 avatar stof 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  avatar  avatar

mini-throttle's Issues

The throttle is not performing as expected.

The throttle of this library does not perform throttling (it behaves differently from what is described in the tests and documentation).

You will understand if you try the following reproduction code in RunKit. Instead of behaving like the marble in the test cases, it appears to perform a complete debounce operation, firing only once at the start and once at the end.

| throttle(fn, 100) | 1 2 4 6 8 10 |

image

var {throttle} = require("@github/mini-throttle")

const delay = (m) => new Promise(r => setTimeout(r, m))

const fn = throttle((...x)=>{console.log(x)},1000)

for (let i = 1; i <= 10; ++i) {
  fn(i)
  await delay(100)
}
await delay(1000)

You can also repro this in the following CodeSandbox. Please rapidly click the button. While the expected throttle behavior is that of lodash.throttle, but mini-throttle does not perform as its name "throttle".

https://codesandbox.io/p/sandbox/damp-browser-fyd2g4?file=/src/index.js:24,11

Better types for the returned function

Currently, the type for the throttled function are not very helpful, because arguments are unknown. But we actually know the argument signature: the same than the original function.
I looked at type declarations for other throttle implementations in the wild to compare the options:

I think a way to go would look like that:

interface Cancelable {
  cancel(): void;
}

export function throttle<T extends (...args: unknown[]) => unknown>(
  callback: T,
  wait = 0,
  {start = true, middle = true, once = false}: ThrottleOptions = {}
): ((...funcArgs: Parameters<T>) => void) & Cancelable {
  // ...
}

Being a JS user (using typescript types to run Typescript in type-checking mode on JS files and to power IDE completion), I'm not sure what are the backward-compatibility effect of changing the type of the generic. It might be a BC break for code specifying the type explicitly (i.e. throttle<SomeType>(myfunc, 10) when calling it). For people relying on type inference, there should be no BC break (unless you consider that a type failure due to a misuse of the throttled function is a BC break, when it would very likely prevent getting a runtime failure due to the wrong arguments).

What do you think about that ? Should I submit a PR ?

Throttle is skipping the last event

Hi, not sure if I am confused or if it is a bug, but while debounce works well, the throttle is skipping the last event (number 10 in the example "marble chart" in Readme). It seems it is not resetting the time window after the given timeout, other libraries are doing it (I checked Rx and Lodash)

a minimal example comparing mini-throttle with lodash throttle: https://codesandbox.io/p/sandbox/damp-browser-fyd2g4?file=%2Fsrc%2Findex.js%3A1%2C1-26%2C1

slow and fast events:

CleanShot.2023-07-17.at.11.23.12.mp4
CleanShot.2023-07-17.at.11.21.55.mp4

middle: true with throttle

Maybe I misunderstood something, but the current default behaviour of middle: true seems a bit surprising to me.

Currently, if one calls the function for the first time, it will get invoked.
Then, if the function gets called again while the delay is still in place, it will get deferred until the next time.
And finally, if the function gets called after the delay is over, nothing seems to happen.

Here is a little snippet to reproduce this

x = throttle(() => console.log("called"), 1000) // throttle 1 second

x() // call x
setTimeout(() => {console.log("x doesn't happen"); x(); }, 5000) // call again in 5 seconds

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.