import {Resolvable} from '.'; export type EachHandler = ( value: T, index: number, values: T[], ) => Resolvable; /** * Asynchronous version of `Array#forEach()`. */ export async function each( values: T[], handler: EachHandler, ): Promise { for (let i = 0; i < values.length; i++) { if ((await handler(values[i], i, values)) === false) { return false; } } return true; } export type SomeHandler = ( value: T, index: number, values: T[], ) => Resolvable; /** * Asynchronous version of `Array#some()`. */ export async function some( values: T[], handler: SomeHandler, ): Promise { for (let i = 0; i < values.length; i++) { if (await handler(values[i], i, values)) { return true; } } return false; } export type EveryHandler = ( value: T, index: number, values: T[], ) => Resolvable; /** * Asynchronous version of `Array#every()`. */ export async function every( values: T[], handler: EveryHandler, ): Promise { for (let i = 0; i < values.length; i++) { if (!await handler(values[i], i, values)) { return false; } } return true; } export type MapTransformer = ( value: T, index: number, values: T[], ) => Resolvable; /** * Asynchronous version of `Array#map()` with basic concurrency control. */ export async function map( values: T[], transformer: MapTransformer, concurrency?: number, ): Promise { if (typeof concurrency !== 'number') { return Promise.all(values.map(transformer)); } return new Promise((resolve, reject) => { let starting = Math.min(concurrency, values.length); let results = [] as TResult[]; if (starting <= 0) { resolve(results); return; } let pending = 0; let i = 0; while (i < starting) { next(); } function next(): void { if (i === values.length) { if (!pending) { resolve(results); } return; } let index = i++; let value = values[index]; pending++; let ret: Resolvable; try { ret = transformer(value, index, values); } catch (error) { reject(error); return; } Promise.resolve(ret).then( result => { results[index] = result; pending--; next(); }, error => { reject(error); }, ); } }); } export type ReduceTransformer = ( result: TResult, value: T, index: number, values: T[], ) => Resolvable; /** * Asynchronous version of `Array#reduce()`. */ export async function reduce( values: T[], transformer: ReduceTransformer, initial: TResult, ): Promise; export async function reduce( values: T[], transformer: ReduceTransformer, ): Promise; export async function reduce( values: T[], transformer: ReduceTransformer, ...args: any[] ): Promise { return (values.reduce as Function)( async (result: TResult, value: T, index: number) => { return transformer(await result, value, index, values); }, ...args, ); } /** * Asynchronous version of `Array#reduceRight()`. */ export async function reduceRight( values: T[], transformer: ReduceTransformer, initial: TResult, ): Promise; export async function reduceRight( values: T[], transformer: ReduceTransformer, ): Promise; export async function reduceRight( values: T[], transformer: ReduceTransformer, ...args: any[] ): Promise { return (values.reduceRight as Function)( async (result: TResult, value: T, index: number) => { return transformer(await result, value, index, values); }, ...args, ); } export type FilterHandler = ( value: T, index: number, values: T[], ) => Resolvable; /** * Asynchronous version of `Array#filter()`. */ export async function filter( values: T[], handler: FilterHandler, ): Promise { let results = [] as T[]; for (let i = 0; i < values.length; i++) { let value = values[i]; if (await handler(value, i, values)) { results.push(value); } } return results; } export type FindHandler = ( value: T, index: number, values: T[], ) => Resolvable; /** * Asynchronous version of `Array#find()`. */ export async function find( values: T[], handler: FindHandler, ): Promise { for (let i = 0; i < values.length; i++) { let value = values[i]; if (await handler(value, i, values)) { return value; } } return undefined; } /** * Asynchronous version of `Array#findIndex()`. */ export async function findIndex( values: T[], handler: FindHandler, ): Promise { for (let i = 0; i < values.length; i++) { if (await handler(values[i], i, values)) { return i; } } return -1; }