+46
-5
@@ -23,2 +23,5 @@ export type LimitFunction = { | ||
| Note: This does not cancel promises that are already running. | ||
| When `rejectOnClear` is enabled, pending promises are rejected with an `AbortError`. | ||
| This is recommended if you await the returned promises, for example with `Promise.all`, so pending tasks do not remain unresolved after `clearQueue()`. | ||
| */ | ||
@@ -32,5 +35,7 @@ clearQueue: () => void; | ||
| This is a convenience function for processing inputs that arrive in batches. For more complex use cases, see [p-map](https://github.com/sindresorhus/p-map). | ||
| @param iterable - An iterable containing an argument for the given function. | ||
| @param mapperFunction - Promise-returning/async function. | ||
| @returns A Promise that returns an array of results. | ||
| @returns A promise equivalent to `Promise.all(Array.from(iterable, (item, index) => limit(mapperFunction, item, index)))`. | ||
| */ | ||
@@ -44,3 +49,6 @@ map: <Input, ReturnType> ( | ||
| @param fn - Promise-returning/async function. | ||
| @param arguments - Any arguments to pass through to `fn`. Support for passing arguments on to the `fn` is provided in order to be able to avoid creating unnecessary closures. You probably don't need this optimization unless you're pushing a lot of functions. | ||
| @param arguments - Any arguments to pass through to `fn`. Support for passing arguments on to the `fn` is provided in order to be able to avoid creating unnecessary closures. You probably don't need this optimization unless you're pushing a *lot* of functions. | ||
| Warning: Avoid calling the same `limit` function inside a function that is already limited by it. This can create a deadlock where inner tasks never run. Use a separate limiter for inner tasks. | ||
| @returns The promise returned by calling `fn(...arguments)`. | ||
@@ -57,6 +65,30 @@ */ | ||
| @param concurrency - Concurrency limit. Minimum: `1`. | ||
| @param concurrency - Concurrency limit. Minimum: `1`. You can pass a number or an options object with a `concurrency` property. | ||
| @returns A `limit` function. | ||
| @example | ||
| ``` | ||
| import pLimit from 'p-limit'; | ||
| const limit = pLimit(1); | ||
| const input = [ | ||
| limit(() => fetchSomething('foo')), | ||
| limit(() => fetchSomething('bar')), | ||
| limit(() => doSomething()) | ||
| ]; | ||
| // Only one promise is run at once | ||
| const result = await Promise.all(input); | ||
| console.log(result); | ||
| ``` | ||
| @example | ||
| ``` | ||
| import pLimit from 'p-limit'; | ||
| const limit = pLimit({concurrency: 1}); | ||
| ``` | ||
| */ | ||
| export default function pLimit(concurrency: number): LimitFunction; | ||
| export default function pLimit(concurrency: number | Options): LimitFunction; | ||
@@ -67,5 +99,14 @@ export type Options = { | ||
| Minimum: `1`. | ||
| Minimum: `1`. | ||
| */ | ||
| readonly concurrency: number; | ||
| /** | ||
| Reject pending promises with an `AbortError` when `clearQueue()` is called. | ||
| Default: `false`. | ||
| This is recommended if you await the returned promises, for example with `Promise.all`, so pending tasks do not remain unresolved after `clearQueue()`. | ||
| */ | ||
| readonly rejectOnClear?: boolean; | ||
| }; | ||
@@ -72,0 +113,0 @@ |
+29
-8
| import Queue from 'yocto-queue'; | ||
| export default function pLimit(concurrency) { | ||
| let rejectOnClear = false; | ||
| if (typeof concurrency === 'object') { | ||
| ({concurrency, rejectOnClear = false} = concurrency); | ||
| } | ||
| validateConcurrency(concurrency); | ||
| if (typeof rejectOnClear !== 'boolean') { | ||
| throw new TypeError('Expected `rejectOnClear` to be a boolean'); | ||
| } | ||
| const queue = new Queue(); | ||
@@ -13,3 +23,3 @@ let activeCount = 0; | ||
| activeCount++; | ||
| queue.dequeue()(); | ||
| queue.dequeue().run(); | ||
| } | ||
@@ -41,7 +51,10 @@ }; | ||
| const enqueue = (function_, resolve, arguments_) => { | ||
| const enqueue = (function_, resolve, reject, arguments_) => { | ||
| const queueItem = {reject}; | ||
| // Queue the internal resolve function instead of the run function | ||
| // to preserve the asynchronous execution context. | ||
| new Promise(internalResolve => { // eslint-disable-line promise/param-names | ||
| queue.enqueue(internalResolve); | ||
| queueItem.run = internalResolve; | ||
| queue.enqueue(queueItem); | ||
| }).then(run.bind(undefined, function_, resolve, arguments_)); // eslint-disable-line promise/prefer-await-to-then | ||
@@ -55,4 +68,4 @@ | ||
| const generator = (function_, ...arguments_) => new Promise(resolve => { | ||
| enqueue(function_, resolve, arguments_); | ||
| const generator = (function_, ...arguments_) => new Promise((resolve, reject) => { | ||
| enqueue(function_, resolve, reject, arguments_); | ||
| }); | ||
@@ -69,3 +82,12 @@ | ||
| value() { | ||
| queue.clear(); | ||
| if (!rejectOnClear) { | ||
| queue.clear(); | ||
| return; | ||
| } | ||
| const abortError = AbortSignal.abort().reason; | ||
| while (queue.size > 0) { | ||
| queue.dequeue().reject(abortError); | ||
| } | ||
| }, | ||
@@ -100,4 +122,3 @@ }, | ||
| export function limitFunction(function_, options) { | ||
| const {concurrency} = options; | ||
| const limit = pLimit(concurrency); | ||
| const limit = pLimit(options); | ||
@@ -104,0 +125,0 @@ return (...arguments_) => limit(() => function_(...arguments_)); |
+1
-1
| { | ||
| "name": "p-limit", | ||
| "version": "7.2.0", | ||
| "version": "7.3.0", | ||
| "description": "Run multiple promise-returning & async functions with limited concurrency", | ||
@@ -5,0 +5,0 @@ "license": "MIT", |
+34
-1
@@ -39,3 +39,3 @@ # p-limit | ||
| Type: `number`\ | ||
| Type: `number | object`\ | ||
| Minimum: `1` | ||
@@ -45,2 +45,18 @@ | ||
| You can pass a number or an options object with a `concurrency` property. | ||
| #### rejectOnClear | ||
| Type: `boolean`\ | ||
| Default: `false` | ||
| Reject pending promises with an `AbortError` when `clearQueue()` is called. | ||
| This is recommended if you await the returned promises, for example with `Promise.all`, so pending tasks do not remain unresolved after `clearQueue()`. | ||
| ```js | ||
| import pLimit from 'p-limit'; | ||
| const limit = pLimit({concurrency: 1}); | ||
| ``` | ||
| ### limit(fn, ...args) | ||
@@ -62,2 +78,4 @@ | ||
| Warning: Avoid calling the same `limit` function inside a function that is already limited by it. This can create a deadlock where inner tasks never run. Use a separate limiter for inner tasks. | ||
| ### limit.map(iterable, mapperFunction) | ||
@@ -89,2 +107,5 @@ | ||
| When `rejectOnClear` is enabled, pending promises are rejected with an `AbortError`. | ||
| This is recommended if you await the returned promises, for example with `Promise.all`, so pending tasks do not remain unresolved after `clearQueue()`. | ||
| ### limit.concurrency | ||
@@ -132,2 +153,14 @@ | ||
| #### rejectOnClear | ||
| Type: `boolean`\ | ||
| Default: `false` | ||
| Reject pending promises with an `AbortError` when `clearQueue()` is called. | ||
| This is recommended if you await the returned promises, for example with `Promise.all`, so pending tasks do not remain unresolved after `clearQueue()`. | ||
| ## Recipes | ||
| See [recipes.md](recipes.md) for common use cases and patterns. | ||
| ## FAQ | ||
@@ -134,0 +167,0 @@ |
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
14881
26.82%205
26.54%174
23.4%5
66.67%