Giter Club home page Giter Club logo

Comments (25)

Richienb avatar Richienb commented on May 22, 2024 1

I'm assuming you want to execute a promise-returning function unless it is already running.

Since I can't add a module, here's how it would work:

const pStateThrottle = async function_ => {
	let isRunning = false

	return (...arguments_) => {
		if (!isRunning) {
			try {
				isRunning = true
				return await function_(…arguments_)
			} finally {
				isRunning = false
			}
		}
	}
}

const action = pStateThrottle(async () => {
	await delay(3000)
	alert("Waited 3 seconds")
})

button.onclick = action

from promise-fun.

fregante avatar fregante commented on May 22, 2024 1

Looks good. I'd use try/finally to return the value and ensure that the state is always updated

		try {
			isRunning = true
			return await function_(…arguments_)
		} finally {
			isRunning = false
		}

from promise-fun.

sindresorhus avatar sindresorhus commented on May 22, 2024 1

@Richienb You don't need the boolean then.

from promise-fun.

sindresorhus avatar sindresorhus commented on May 22, 2024 1

@fregante Or a separate method? debounce.single/debounce.wait/debounce.one.

Also, related issue: sindresorhus/p-debounce#3

from promise-fun.

sindresorhus avatar sindresorhus commented on May 22, 2024

I wonder if this could be an option or separate method to https://github.com/sindresorhus/p-debounce

from promise-fun.

sindresorhus avatar sindresorhus commented on May 22, 2024

Alternative names:

  • p-dedupe
  • p-deduplicate
  • p-ensure-one

from promise-fun.

sindresorhus avatar sindresorhus commented on May 22, 2024

Just nitpick, I would make it return early:

const pStateThrottle = async function_ => {
	let isRunning = false

	return (...arguments_) => {
		if (isRunning) {
			return
		}

		try {
			isRunning = true
			return await function_(…arguments_)
		} finally {
			isRunning = false
		}
	}
}

const action = pStateThrottle(async () => {
	await delay(3000)
	alert("Waited 3 seconds")
})

button.onclick = action

from promise-fun.

sindresorhus avatar sindresorhus commented on May 22, 2024

Currently, when called a second time, it will just resolve the promise right away. That's fine for this specific use-case, but I think it might be better to store the promise and return that instead. That way the second call would wait for the original delay to finish too.

from promise-fun.

Richienb avatar Richienb commented on May 22, 2024

I think it might be better to store the promise and return that instead.

const pStateThrottle = function_ => {
	let currentPromise

	return async (...arguments_) => {
		if (currentPromise) {
			return currentPromise
		}

		try {
			currentPromise = function_(...arguments_)
			return await currentPromise
		} finally {
			currentPromise = undefined
		}
	}
}

const action = pStateThrottle(async () => {
	await delay(3000)
	alert("Waited 3 seconds")
})

button.onclick = action

from promise-fun.

fregante avatar fregante commented on May 22, 2024

I wonder if this could be an option or separate method to sindresorhus/p-debounce

Only if it's an alternative to the timer rather than an addition (i.e. just "wait for the promise", never "wait for the promise and the timer")

Given that none of the options apply to this behavior, the signature can become:

function debounce(fn, [wait, [options]])

No wait means it just waits for the Promise.


Alternatively it could be p-one-pending because deduplication makes me think of memoization

from promise-fun.

fregante avatar fregante commented on May 22, 2024

debounce.promise would make the most sense to me, or debounce.whilePending?

from promise-fun.

Richienb avatar Richienb commented on May 22, 2024

Debouncing queues extra calls to be run after a delay whereas throttling dumps extra calls without ever executing them. We are actually throttling function calls so we should add it to https://github.com/sindresorhus/p-throttle.

from promise-fun.

fregante avatar fregante commented on May 22, 2024

Debouncing queues extra calls to be run after a delay

No, debouncing does not queue calls. Only p-debounce returns the same promise for all the calls, but usually debouncers drop calls and return undefined. In fact they're often used in event listeners like window.onresize = debounce(callback, 300) so that they're only called once the resize events stop.

Throttling calls the function "no more often than every X milliseconds", so I don't think it applies here.

from promise-fun.

fregante avatar fregante commented on May 22, 2024

Therefore, this should result in one alert:

const action = debounce.promise(async () => {
	delay(3000);
	alert('Done')!
})

action();
action();

from promise-fun.

Richienb avatar Richienb commented on May 22, 2024

I've begun implementing this in p-debounce and I've come to this realisation: What is this supposed to do?

const action = debounce.promise(async value => {
	delay(3000);
	return value
})

action("a");
action("b");

Right now, it throws away "b" which leads to unpredictable results as the second call will resolve with a.

Do we want to queue up calls instead of discarding them in a separate implementation in p-throttle?

from promise-fun.

fregante avatar fregante commented on May 22, 2024

Right now, it throws away "b" which leads to unpredictable results as the second call will resolve with a.

That's what debounce does, it discards calls:

https://github.com/sindresorhus/p-debounce/blob/46ed3aab5974c2ced01a166233965bfa129de9ce/test.js#L45-L50

Do we want to queue up calls instead of discarding them in a separate implementation in p-throttle?

Throttle discards calls too. You're thinking of queues, which neither debounce nor throttle are.

from promise-fun.

Richienb avatar Richienb commented on May 22, 2024

Throttle discards calls too. You're thinking of queues, which neither debounce nor throttle are.

p-throttle defines queue:

https://github.com/sindresorhus/p-throttle/blob/004bcd3d837bc24ca55a88f8c4c8896a95545c91/index.js#L19

from promise-fun.

fregante avatar fregante commented on May 22, 2024

Indeed.

How's p-throttle different from p-limit? It appears the same down to the concurrency option.

p-throttle is the only "throttle" module that behaves this way. See this example, none of them execute the calls 2, and 3 except p-throttle.

https://runkit.com/bfred-it/5ffe7a7977172c001b32528f

from promise-fun.

sindresorhus avatar sindresorhus commented on May 22, 2024

p-throttle is the only "throttle" module that behaves this way. See this example, none of them execute the calls 2, and 3 except p-throttle.

Yeah, I don't remember why I made it like that. Seems you're not the only confused one: sindresorhus/p-throttle#15 Maybe we should add a discard option and make it default to true? That way the default behavior is the expected one and users can set it to false to get the old behavior.

from promise-fun.

Richienb avatar Richienb commented on May 22, 2024

Since this new function also discards calls, does it still make sense for it to be added to p-debounce?

from promise-fun.

fregante avatar fregante commented on May 22, 2024

Yeah, I don't remember why I made it like that

If I think about it it does make sense as it does throttle calls; the only issue is that it doesn't match the meaning throttle has in the JS community.

How's p-throttle different from p-limit?

Answering myself: p-limit doesn't have an interval parameter

from promise-fun.

fregante avatar fregante commented on May 22, 2024

I think this should/could be part of p-memoize:

  • it supports multiple calls at once, as long as the parameters are different
  • can support "one call at once regardless of parameters" by just passing cacheKey: () => {} probably

In practice this is identical but opposite to cachePromiseRejection. I'll open an issue there.

from promise-fun.

etienne-martin avatar etienne-martin commented on May 22, 2024

Alternative names:

  • p-dedupe
  • p-deduplicate
  • p-ensure-one

I suggest the name p-collapse, as the behavior is similar to request collapsing on CDNs.

Request collapsing is the practice of combining multiple requests for the same object into a single request to origin, and then using the resulting response to satisfy all pending requests.

from promise-fun.

fregante avatar fregante commented on May 22, 2024

Closing in favor of sindresorhus/p-memoize#20

from promise-fun.

TehShrike avatar TehShrike commented on May 22, 2024

@fregante you may be interested in https://github.com/TehShrike/gate-keeper

from promise-fun.

Related Issues (9)

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.