{"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.mapAsync} and {@link Async.forEachAsync}.\n *\n * @beta\n */\nexport interface IAsyncParallelismOptions {\n /**\n * Optionally used with the {@link Async.mapAsync} and {@link Async.forEachAsync}\n * to limit the maximum number of concurrent promises to the specified number.\n */\n concurrency?: number;\n}\n\n/**\n * @remarks\n * Used with {@link Async.runWithRetriesAsync}.\n *\n * @beta\n */\nexport interface IRunWithRetriesOptions {\n action: () => Promise | TResult;\n maxRetries: number;\n retryDelayMs?: number;\n}\n\n/**\n * Utilities for parallel asynchronous operations, for use with the system `Promise` APIs.\n *\n * @beta\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 | undefined\n ): Promise {\n const result: TRetVal[] = [];\n\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 /**\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 | 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 operationsInProgress: number = 0;\n\n const iterator: Iterator | AsyncIterator = (\n (iterable as Iterable)[Symbol.iterator] ||\n (iterable as AsyncIterable)[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 (operationsInProgress < concurrency && !iteratorIsComplete && !promiseHasResolvedOrRejected) {\n // Increment the concurrency while waiting for the iterator.\n // This function is reentrant, so this ensures that at most `concurrency` executions are waiting\n operationsInProgress++;\n const currentIteratorResult: IteratorResult = await iterator.next();\n // eslint-disable-next-line require-atomic-updates\n iteratorIsComplete = !!currentIteratorResult.done;\n\n if (!iteratorIsComplete) {\n Promise.resolve(callback(currentIteratorResult.value, arrayIndex++))\n .then(async () => {\n operationsInProgress--;\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 operationsInProgress--;\n }\n }\n\n if (iteratorIsComplete) {\n await onOperationCompletionAsync();\n }\n }\n\n async function onOperationCompletionAsync(): Promise {\n if (!promiseHasResolvedOrRejected) {\n if (operationsInProgress === 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 * Return a promise that resolves after the specified number of milliseconds.\n */\n public static async sleep(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.sleep(retryDelayMs);\n }\n }\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"]}