async-throttle
Throttle async and promise returning functions. Unlike similarly named packages, this behaves much like an async version of
lodash.throttle
:
- Only one invocation can be running at a time (similarly named packages don't do this)
- Has
.cancel()
and .flush()
Differences from lodash.throttle
- No
leading
and trailing
options getNextArgs
option allows you to customize how the arguments for the next invocation are determined
Installing
npm install --save @jcoreio/async-throttle
Usage
const throttle = require('@jcoreio/async-throttle')
import throttle from '@jcoreio/async-throttle'
function throttle<Args: Array<any>, Value>(
func: (...args: Args) => Promise<Value>,
wait: ?number,
options?: {
getNextArgs?: (current: Args, next: Args) => Args
}
): (...args: Args) => Promise<Value>;
Creates a throttled function that only invokes func
at most once per every wait
milliseconds, and also waits for the
Promise
returned by the previous invocation to finish (it won't invoke func
in parallel).
The promise returned by the throttled function will track the promise returned by the next invocation of func
.
If wait
is falsy, it is treated as 0, which causes func
to be invoked on the next tick afte the previous invocation
finishes.
By default, func
is called with the most recent arguments to the throttled function. You can change this with the
getNextArgs
option -- for example, if you want to invoke func
with the minimum of all arguments since the last
invocation:
const throttledFn = throttle(foo, 10, {
getNextArgs: ([a], [b]) => [Math.min(a, b)],
})
throttledFn(2)
throttledFn(1)
throttledFn(3)
throttledFn(4)
throttledFn(6)
throttledFn(5)
throttledFn.invokeIgnoreResult(args)
Calls the throttled function soon, but doesn't return a promise, catches any CanceledError, and doesn't create any new promises if a call is already pending.
To use this, you should handle all errors inside the throttled function:
const throttled = throttle(async (arg) => {
try {
await doSomething(arg)
} catch (err) {
}
})
Then call invokeIgnoreResult
instead of the throttled function:
throttled.invokeIgnoreResult(arg)
The invokeIgnoreResult
method is useful because the following code example would leave 1000 pending promises
on the heap, even though the catch block is a no-op:
for (let i = 0; i < 1000; i++) {
throttled(arg).catch(() => {})
}
throttledFn.cancel()
Cancels the pending invocation, if any. All Promise
s tracking the pending invocation will be
rejected with a CancelationError
(const {CancelationError} = require('@jcoreio/async-throttle')
).
However, if an invocation is currently running, all Promise
s tracking the current invocation will be fulfilled as usual.
Returns a Promise
that will resolve once the current invocation (if any) is finished.
throttledFn.flush()
Cancels the wait
before the pending invocation, if any. The pending invocation will still wait for the current invocation (if any)
to finish, but will begin immediately afterward, even if wait
has not elapsed.
Returns a Promise
that will resolve once the current invocation (if any) is finished.