{"version":3,"file":"Async.js","sourceRoot":"","sources":["../src/Async.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\n/**\n * Options for controlling the parallelism of asynchronous operations.\n *\n * @remarks\n * Used with {@link (Async:class).(mapAsync:1)}, {@link (Async:class).(mapAsync:2)} and\n * {@link (Async:class).(forEachAsync:1)}, and {@link (Async:class).(forEachAsync:2)}.\n *\n * @public\n */\nexport interface IAsyncParallelismOptions {\n /**\n * Optionally used with the {@link (Async:class).(mapAsync:1)}, {@link (Async:class).(mapAsync:2)} and\n * {@link (Async:class).(forEachAsync:1)}, and {@link (Async:class).(forEachAsync:2)} to limit the maximum\n * number of concurrent promises to the specified number.\n */\n concurrency?: number;\n\n /**\n * Optionally used with the {@link (Async:class).(forEachAsync:2)} to enable weighted operations where an operation can\n * take up more or less than one concurrency unit.\n */\n weighted?: boolean;\n}\n\n/**\n * @remarks\n * Used with {@link Async.runWithRetriesAsync}.\n *\n * @public\n */\nexport interface IRunWithRetriesOptions {\n action: () => Promise | TResult;\n maxRetries: number;\n retryDelayMs?: number;\n}\n\n/**\n * @remarks\n * Used with {@link (Async:class).(forEachAsync:2)} and {@link (Async:class).(mapAsync:2)}.\n *\n * @public\n */\nexport interface IWeighted {\n /**\n * The weight of the element, used to determine the concurrency units that it will take up.\n * Must be a whole number greater than or equal to 0.\n */\n weight: number;\n}\n\nfunction toWeightedIterator(\n iterable: Iterable | AsyncIterable,\n useWeights?: boolean\n): AsyncIterable<{ element: TEntry; weight: number }> {\n const iterator: Iterator | AsyncIterator = (\n (iterable as Iterable)[Symbol.iterator] ||\n (iterable as AsyncIterable)[Symbol.asyncIterator]\n ).call(iterable);\n return {\n [Symbol.asyncIterator]: () => ({\n // eslint-disable-next-line @typescript-eslint/naming-convention\n next: async () => {\n // The await is necessary here, but TS will complain - it's a false positive.\n const { value, done } = await iterator.next();\n return {\n value: { element: value, weight: useWeights ? value?.weight : 1 },\n done: !!done\n };\n }\n })\n };\n}\n\n/**\n * Utilities for parallel asynchronous operations, for use with the system `Promise` APIs.\n *\n * @public\n */\nexport class Async {\n /**\n * Given an input array and a `callback` function, invoke the callback to start a\n * promise for each element in the array. Returns an array containing the results.\n *\n * @remarks\n * This API is similar to the system `Array#map`, except that the loop is asynchronous,\n * and the maximum number of concurrent promises can be throttled\n * using {@link IAsyncParallelismOptions.concurrency}.\n *\n * If `callback` throws a synchronous exception, or if it returns a promise that rejects,\n * then the loop stops immediately. Any remaining array items will be skipped, and\n * overall operation will reject with the first error that was encountered.\n *\n * @param iterable - the array of inputs for the callback function\n * @param callback - a function that starts an asynchronous promise for an element\n * from the array\n * @param options - options for customizing the control flow\n * @returns an array containing the result for each callback, in the same order\n * as the original input `array`\n */\n public static async mapAsync(\n iterable: Iterable | AsyncIterable,\n callback: (entry: TEntry, arrayIndex: number) => Promise,\n options?: (IAsyncParallelismOptions & { weighted?: false }) | undefined\n ): Promise;\n\n /**\n * Given an input array and a `callback` function, invoke the callback to start a\n * promise for each element in the array. Returns an array containing the results.\n *\n * @remarks\n * This API is similar to the system `Array#map`, except that the loop is asynchronous,\n * and the maximum number of concurrent units can be throttled\n * using {@link IAsyncParallelismOptions.concurrency}. Using the {@link IAsyncParallelismOptions.weighted}\n * option, the weight of each operation can be specified, which determines how many concurrent units it takes up.\n *\n * If `callback` throws a synchronous exception, or if it returns a promise that rejects,\n * then the loop stops immediately. Any remaining array items will be skipped, and\n * overall operation will reject with the first error that was encountered.\n *\n * @param iterable - the array of inputs for the callback function\n * @param callback - a function that starts an asynchronous promise for an element\n * from the array\n * @param options - options for customizing the control flow\n * @returns an array containing the result for each callback, in the same order\n * as the original input `array`\n */\n public static async mapAsync(\n iterable: Iterable | AsyncIterable,\n callback: (entry: TEntry, arrayIndex: number) => Promise,\n options: IAsyncParallelismOptions & { weighted: true }\n ): Promise;\n public static async mapAsync(\n iterable: Iterable | AsyncIterable,\n callback: (entry: TEntry, arrayIndex: number) => Promise,\n options?: IAsyncParallelismOptions | undefined\n ): Promise {\n const result: TRetVal[] = [];\n\n // @ts-expect-error https://github.com/microsoft/TypeScript/issues/22609, it succeeds against the implementation but fails against the overloads\n await Async.forEachAsync(\n iterable,\n async (item: TEntry, arrayIndex: number): Promise => {\n result[arrayIndex] = await callback(item, arrayIndex);\n },\n options\n );\n\n return result;\n }\n\n private static async _forEachWeightedAsync(\n iterable: AsyncIterable,\n callback: (entry: TReturn, arrayIndex: number) => Promise,\n options?: IAsyncParallelismOptions | undefined\n ): Promise {\n await new Promise((resolve: () => void, reject: (error: Error) => void) => {\n const concurrency: number =\n options?.concurrency && options.concurrency > 0 ? options.concurrency : Infinity;\n let concurrentUnitsInProgress: number = 0;\n\n const iterator: Iterator | AsyncIterator = (iterable as AsyncIterable)[\n Symbol.asyncIterator\n ].call(iterable);\n\n let arrayIndex: number = 0;\n let iteratorIsComplete: boolean = false;\n let promiseHasResolvedOrRejected: boolean = false;\n\n async function queueOperationsAsync(): Promise {\n while (\n concurrentUnitsInProgress < concurrency &&\n !iteratorIsComplete &&\n !promiseHasResolvedOrRejected\n ) {\n // Increment the current concurrency units in progress by the concurrency limit before fetching the iterator weight.\n // This function is reentrant, so this if concurrency is finite, at most 1 operation will be waiting. If it's infinite,\n // there will be effectively no cap on the number of operations waiting.\n const limitedConcurrency: number = !Number.isFinite(concurrency) ? 1 : concurrency;\n concurrentUnitsInProgress += limitedConcurrency;\n const currentIteratorResult: IteratorResult = await iterator.next();\n // eslint-disable-next-line require-atomic-updates\n iteratorIsComplete = !!currentIteratorResult.done;\n\n if (!iteratorIsComplete) {\n const currentIteratorValue: TEntry = currentIteratorResult.value;\n Async.validateWeightedIterable(currentIteratorValue);\n // Cap the weight to concurrency, this allows 0 weight items to execute despite the concurrency limit.\n const weight: number = Math.min(currentIteratorValue.weight, concurrency);\n\n // Remove the \"lock\" from the concurrency check and only apply the current weight.\n // This should allow other operations to execute.\n concurrentUnitsInProgress += weight;\n concurrentUnitsInProgress -= limitedConcurrency;\n\n Promise.resolve(callback(currentIteratorValue.element, arrayIndex++))\n .then(async () => {\n // Remove the operation completely from the in progress units.\n concurrentUnitsInProgress -= weight;\n await onOperationCompletionAsync();\n })\n .catch((error) => {\n promiseHasResolvedOrRejected = true;\n reject(error);\n });\n } else {\n // The iterator is complete and there wasn't a value, so untrack the waiting state.\n concurrentUnitsInProgress -= limitedConcurrency;\n }\n }\n\n if (iteratorIsComplete) {\n await onOperationCompletionAsync();\n }\n }\n\n async function onOperationCompletionAsync(): Promise {\n if (!promiseHasResolvedOrRejected) {\n if (concurrentUnitsInProgress === 0 && iteratorIsComplete) {\n promiseHasResolvedOrRejected = true;\n resolve();\n } else if (!iteratorIsComplete) {\n await queueOperationsAsync();\n }\n }\n }\n\n queueOperationsAsync().catch((error) => {\n promiseHasResolvedOrRejected = true;\n reject(error);\n });\n });\n }\n\n /**\n * Given an input array and a `callback` function, invoke the callback to start a\n * promise for each element in the array.\n *\n * @remarks\n * This API is similar to the system `Array#forEach`, except that the loop is asynchronous,\n * and the maximum number of concurrent promises can be throttled\n * using {@link IAsyncParallelismOptions.concurrency}.\n *\n * If `callback` throws a synchronous exception, or if it returns a promise that rejects,\n * then the loop stops immediately. Any remaining array items will be skipped, and\n * overall operation will reject with the first error that was encountered.\n *\n * @param iterable - the array of inputs for the callback function\n * @param callback - a function that starts an asynchronous promise for an element\n * from the array\n * @param options - options for customizing the control flow\n */\n public static async forEachAsync(\n iterable: Iterable | AsyncIterable,\n callback: (entry: TEntry, arrayIndex: number) => Promise,\n options?: (IAsyncParallelismOptions & { weighted?: false }) | undefined\n ): Promise;\n\n /**\n * Given an input array and a `callback` function, invoke the callback to start a\n * promise for each element in the array.\n *\n * @remarks\n * This API is similar to the other `Array#forEachAsync`, except that each item can have\n * a weight that determines how many concurrent operations are allowed. The unweighted\n * `Array#forEachAsync` is a special case of this method where weight = 1 for all items.\n *\n * The maximum number of concurrent operations can still be throttled using\n * {@link IAsyncParallelismOptions.concurrency}, however it no longer determines the\n * maximum number of operations that can be in progress at once. Instead, it determines the\n * number of concurrency units that can be in progress at once. The weight of each operation\n * determines how many concurrency units it takes up. For example, if the concurrency is 2\n * and the first operation has a weight of 2, then only one more operation can be in progress.\n *\n * If `callback` throws a synchronous exception, or if it returns a promise that rejects,\n * then the loop stops immediately. Any remaining array items will be skipped, and\n * overall operation will reject with the first error that was encountered.\n *\n * @param iterable - the array of inputs for the callback function\n * @param callback - a function that starts an asynchronous promise for an element\n * from the array\n * @param options - options for customizing the control flow\n */\n public static async forEachAsync(\n iterable: Iterable | AsyncIterable,\n callback: (entry: TEntry, arrayIndex: number) => Promise,\n options: IAsyncParallelismOptions & { weighted: true }\n ): Promise;\n public static async forEachAsync(\n iterable: Iterable | AsyncIterable,\n callback: (entry: TEntry, arrayIndex: number) => Promise,\n options?: IAsyncParallelismOptions\n ): Promise {\n await Async._forEachWeightedAsync(toWeightedIterator(iterable, options?.weighted), callback, options);\n }\n\n /**\n * Return a promise that resolves after the specified number of milliseconds.\n */\n public static async sleepAsync(ms: number): Promise {\n await new Promise((resolve) => {\n setTimeout(resolve, ms);\n });\n }\n\n /**\n * Executes an async function and optionally retries it if it fails.\n */\n public static async runWithRetriesAsync({\n action,\n maxRetries,\n retryDelayMs = 0\n }: IRunWithRetriesOptions): Promise {\n let retryCounter: number = 0;\n // eslint-disable-next-line no-constant-condition\n while (true) {\n try {\n return await action();\n } catch (e) {\n if (++retryCounter > maxRetries) {\n throw e;\n } else if (retryDelayMs > 0) {\n await Async.sleepAsync(retryDelayMs);\n }\n }\n }\n }\n\n /**\n * Ensures that the argument is a valid {@link IWeighted}, with a `weight` argument that\n * is a positive integer or 0.\n */\n public static validateWeightedIterable(operation: IWeighted): void {\n if (operation.weight < 0) {\n throw new Error('Weight must be a whole number greater than or equal to 0');\n }\n if (operation.weight % 1 !== 0) {\n throw new Error('Weight must be a whole number greater than or equal to 0');\n }\n }\n\n /**\n * Returns a Signal, a.k.a. a \"deferred promise\".\n */\n public static getSignal(): [Promise, () => void, (err: Error) => void] {\n return getSignal();\n }\n}\n\n/**\n * Returns an unwrapped promise.\n */\nfunction getSignal(): [Promise, () => void, (err: Error) => void] {\n let resolver: () => void;\n let rejecter: (err: Error) => void;\n const promise: Promise = new Promise((resolve, reject) => {\n resolver = resolve;\n rejecter = reject;\n });\n return [promise, resolver!, rejecter!];\n}\n\n/**\n * A queue that allows for asynchronous iteration. During iteration, the queue will wait until\n * the next item is pushed into the queue before yielding. If instead all queue items are consumed\n * and all callbacks have been called, the queue will return.\n *\n * @public\n */\nexport class AsyncQueue implements AsyncIterable<[T, () => void]> {\n private _queue: T[];\n private _onPushSignal: Promise;\n private _onPushResolve: () => void;\n\n public constructor(iterable?: Iterable) {\n this._queue = iterable ? Array.from(iterable) : [];\n const [promise, resolver] = getSignal();\n this._onPushSignal = promise;\n this._onPushResolve = resolver;\n }\n\n public async *[Symbol.asyncIterator](): AsyncIterableIterator<[T, () => void]> {\n let activeIterations: number = 0;\n let [callbackSignal, callbackResolve] = getSignal();\n const callback: () => void = () => {\n if (--activeIterations === 0) {\n // Resolve whatever the latest callback promise is and create a new one\n callbackResolve();\n const [newCallbackSignal, newCallbackResolve] = getSignal();\n callbackSignal = newCallbackSignal;\n callbackResolve = newCallbackResolve;\n }\n };\n\n let position: number = 0;\n while (this._queue.length > position || activeIterations > 0) {\n if (this._queue.length > position) {\n activeIterations++;\n yield [this._queue[position++], callback];\n } else {\n // On push, the item will be added to the queue and the onPushSignal will be resolved.\n // On calling the callback, active iterations will be decremented by the callback and the\n // callbackSignal will be resolved. This means that the loop will continue if there are\n // active iterations or if there are items in the queue that haven't been yielded yet.\n await Promise.race([this._onPushSignal, callbackSignal]);\n }\n }\n }\n\n /**\n * Adds an item to the queue.\n *\n * @param item - The item to push into the queue.\n */\n public push(item: T): void {\n this._queue.push(item);\n this._onPushResolve();\n const [onPushSignal, onPushResolve] = getSignal();\n this._onPushSignal = onPushSignal;\n this._onPushResolve = onPushResolve;\n }\n}\n"]}