Giter Club home page Giter Club logo

debounce-promise's Introduction

debounce-promise

Build Status Standard - JavaScript Style Guide

NPM

Create a debounced version of a promise returning function

Install

npm i -S debounce-promise

Usage example

var debounce = require('debounce-promise')

function expensiveOperation(value) {
  return Promise.resolve(value)
}

var saveCycles = debounce(expensiveOperation, 100);

[1, 2, 3, 4].forEach(num => {
  return saveCycles('call no #' + num).then(value => {
    console.log(value)
  })
})

// Will only call expensiveOperation once with argument `4` and print:
//=> call no #4
//=> call no #4
//=> call no #4
//=> call no #4

With leading=true

var debounce = require('debounce-promise')

function expensiveOperation(value) {
  return Promise.resolve(value)
}

var saveCycles = debounce(expensiveOperation, 100, {leading: true});

[1, 2, 3, 4].forEach(num => {
  return saveCycles('call no #' + num).then(value => {
    console.log(value)
  })
})

//=> call no #1
//=> call no #4
//=> call no #4
//=> call no #4

With accumulate=true

var debounce = require('debounce-promise')

function squareValues (argTuples) {
  return Promise.all(argTuples.map(args => args[0] * args[0]))
}

var square = debounce(squareValues, 100, {accumulate: true});

[1, 2, 3, 4].forEach(num => {
  return square(num).then(value => {
    console.log(value)
  })
})

//=> 1
//=> 4
//=> 9
//=> 16

Api

debounce(func, [wait=0], [{leading: true|false, accumulate: true|false})

Returns a debounced version of func that delays invoking until after wait milliseconds.

Set leading: true if you want to call func and return its promise immediately.

Set accumulate: true if you want the debounced function to be called with an array of all the arguments received while waiting.

Supports passing a function as the wait parameter, which provides a way to lazily or dynamically define a wait timeout.

Example timeline illustration

function refresh() {
  return fetch('/my/api/something')
}
const debounced = debounce(refresh, 100)
time (ms) ->   0 ---  10  ---  50  ---  100 ---
-----------------------------------------------
debounced()    | --- P(1) --- P(1) --- P(1) ---
refresh()      | --------------------- P(1) ---
const debounced = debounce(refresh, 100, {leading: true})
time (ms) ->   0 ---  10  ---  50  ---  100 ---  110 ---
--------------------------------------------------------
debounced()    | --- P(1) --- P(2) --- P(2) --- P(2) ---
refresh()      | --- P(1) --------------------- P(2) ---

debounce-promise's People

Contributors

bjoerge avatar dortonway avatar idpaterson avatar ilyasemenov avatar nyurik avatar wayne-nlt 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

debounce-promise's Issues

map of deboucing functions

Hi,

Imagine an UI with a list of 10 fields, each have an id, and a value. I want to lazily persist each field value to a backend. I basically have a single api method for this:

export const persistFieldValue = (fieldId, fieldValue) => fetch(...)

I want to debounce this api function, yet the debouncing should only happen on a fieldId level.

I could certainly maintain myself a cache of (fieldId, debouncingFunction), just want to share my usecase and maybe it's worth handling this usecase in this lib?

then is not a function

Hi @bjoerge,

I have one issue with debounce function, here is what I'm doing

const fakeResponseFunc = ({ status, data}) => {
  return new Promise((resolve, reject) => resolve({ status, data })
};

function expensiveOperation() {
  return Promise.resolve(fakeResponseFunc({
      status: 200,
      data: "something",
    }))
    }

const afterDebounce = debounce(expensiveOperation, 300);

afterDebounce.then(({ data }) => console.log(data))

I'm getting for afterDebounce.then is not a function, I use latest v3.1.2 version this is really basic sample and weird that it doesn't do debounce as desired.

Add es2015 definition

When adding it

Uncaught Error: Module build failed: Error: Couldn't find preset \"es2015\" relative to directory \"/my-project/node_modules/debounce-promise\"

Single call option?

I would like to debounce a function returning a promise but also limit the concurrent calls of my function to 1. That is, if a previous promise is still running after the debounce delay is reached, delay again and again... until the last promise finish and the debounce delay is expired (no other calls occured during the waiting time).

In fact, my use case is an async database update: i don't want to update the database too often, and not concurrently either, but I want the last call to be performed so that the latest data goes into the database.

Don't call function later if leading is true

When I set leading: true, I'd expect the function to only be called when it is actually triggered.

Consider a typing indicator for a chat application. I'd like to send the indicator event as soon as the user starts typing, and resend it if they are still typing after every 5 seconds. Currently, if they start typing and stop after 2 seconds, it will send an event on the leading edge (good), then queue the remaining events and send a second one at the end of 5 seconds, even though by then the user isn't typing anymore.

With leading: true, does it make sense to expect all events that can't be sent on the leading edge to be ignored? If there are good use cases to the contrary, would it make sense to add an option to accommodate both?

Handling multiple requests

I would like to optimize multiple expensive server calls with the following logic:

  • on first call, create a promise
  • on each call, accumulate data to be sent to the server
  • when no calls are made for 100 ms, call the server to process all the requests accumulated so far
  • if a new call is made (even if the server hasn't responded yet), treat it as the "first call" - starting a new promise

Can I do something like this with your lib? Thanks!

use of debounce-promise with React. (TypeError: Object(...) is not a function)

In the first attempt to use the debounce-promise with a React component, I'm encountering the following error that can be seen in the screenshot below, also follows the code used, what am I missing?

image

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { fetchUser } from './actions';
import { debounce } from 'debounce-promise';


    class App extends Component {
	constructor(props) {
		super(props);

const _searchAsyncDebounced = debounce(async text => props.fetchUser(text), 500);

		this.handleTextChange = async event => {
			const imageUrl = await _searchAsyncDebounced(event.target.value);
			this.setState({ imageUrl });
		};
	}

	render() {
		let image = '';
		if (this.state.imageUrl) image = <img src={this.state.imageUrl} alt="Not Found" width={100} />;
		return (
			<div>
				<h2>Github Search:</h2>
				<input placeholder="Username" onChange={this.searchUser} />
				<p>{image}</p>
			</div>
		);
	}
}

const mapStateToProps = state => ({
	image: state.user.avatar_url,
});

const mapDispatchToProps = {
	fetchUser,
};

export default connect(
	mapStateToProps,
	mapDispatchToProps
)(App);

dist broken?

Hi there,
I have just updated to the latest version of debounce-promise and the dist/index.js file seems to be broken.
Instead of require("debounce-promise") returning a function, it returns an object with the default key as the function, see below:

Wayne:tmp wayne$ npm install debounce-promise
[email protected] ../node_modules/debounce-promise
Wayne:tmp wayne$ node
> debounce=require("debounce-promise")
{ default: [Function: debounce] }
> debounce
{ default: [Function: debounce] }
> debounce()
TypeError: debounce is not a function
    at repl:1:1
    at REPLServer.defaultEval (repl.js:262:27)
    at bound (domain.js:287:14)
    at REPLServer.runBound [as eval] (domain.js:300:12)
    at REPLServer.<anonymous> (repl.js:431:12)
    at emitOne (events.js:82:20)
    at REPLServer.emit (events.js:169:7)
    at REPLServer.Interface._onLine (readline.js:211:10)
    at REPLServer.Interface._line (readline.js:550:8)
    at REPLServer.Interface._ttyWrite (readline.js:827:14)
>

The docs don't reflect a change in the way it should be called, so I expect it must be a bug with the cleanup work you did recently.

Thanks,
Wayne

Accumulate doesn't work correctly if debounced function returns nothing (undefined)

The error It get is this:

(node:18886) UnhandledPromiseRejectionWarning: TypeError: Cannot read property '0' of undefined
    at /c/repositories/proforto/Profortool/grand-bazaar/packages/tricorp-materializer/node_modules/debounce-promise/dist/index.js:43:23
    at processTicksAndRejections (internal/process/task_queues.js:97:5)
    at async Promise.all (index 0)

Example code:

const debounce = require('debounce-promise')

async function doIt(name) {
    console.log('name', name) // [ [ 'first' ], [ 'second' ], [ 'third' ] ]
    // return name // When returning a value, no error is thrown
}

const doItPlus = debounce(doIt, 100, { accumulate: true })

async function main() {
    const promises = [
        doItPlus('first'),
        doItPlus('second'),
        doItPlus('third'),
    ]

    await Promise.all(promises)
}

main()

Node version: v13.3.0

Ability to "cancel" the resolution of former promises.

Hi,

For this case:

[1, 2, 3, 4].forEach(num => {
  return saveCycles('call no #' + num).then(value => {
    console.log(value)
  })
})

I'd like to be able to output only one log:

// Will only call expensiveOperation once with argument `4` and print:
//=> call no #4

Basically, the first 3 calls I'd like to be able to do:

const promiseResolver => (promise, isLast) => new Promise((resolve, reject) => {
    promise.then(
      value => isLast() && resolve(value),
      error => isLast() && reject(error),
    );
});

Does it make any sense to you to support such an usecase?
I'd be happy to submit a PR for this.

edit: according to what I understand, as of now you return 4 times the same promise so this means it's not possible to do what I want unless returning 4 distinct promises.

Please add a license file

The package.json shows "license": "MIT",, but I do not see a LICENSE file in the repo. Please add one with the MIT license. 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.