import { curry2 } from "./curry" import { head, length } from "./safe" import { AnyFunc, AnyObject, Composed } from "./types" import { isArray } from "./utils" /** One promise waits for another. */ export const forEachSerial = (() => { const pipe = async (fn: AnyFunc, items: any[], i: number) => { if(i pipe(fn, items, 0) ) })() /** Promise.all wrapper for functional pipelining. */ export const waitAll = (promises: Promise[]) => Promise.all(promises) export const qwaitAll = async (xs: Promise[]) => new Promise((ff, rj) => { const len = length(xs); let j = len for(let i=0; i {xs[i]=x as any; if(--j) ff(xs as any)}).catch(rj) }) /** Waits for a Promise that been generated by the first arg, then returns an untoched value. Types T. * @param {AnyFunc} fn - function to wait. * @param {T} s - any value to tap and return back * @returns {T} */ export const waitTap = curry2(async (fn: AnyFunc>, s: any) => { await fn(s); return s }) /** Waits for all promises mapped by the fn. */ export const forEachParallel = curry2( (fn: (item: any) => Promise, items: any[]) => Promise.all(items.map(fn)) ) /** The same as compose, but waits for promises in chains and returns a Promise. */ export const composeAsync = (() => { const pipe = async (fns: AnyFunc[], input: any[], i: number): Promise => ~i ? await pipe(fns, [await fns[i](...input)], --i) : head(input) return (...fns: AnyFunc[]): Composed> => (...input: any[]) => pipe(fns, input, fns.length-1) })() /** * @param cond async (v, k) -> boolean. * @param data T extends any[] | AnyObject. * @returns T */ export const qfilterAsync = curry2(async ( cond: (v: any, k: string | number) => Promise | boolean, data: T // dunno how to merge it with sync version... ): Promise => { if(isArray(data)) { let indicies_offset = 0 const indicies2rm: number[] = [] const len = length(data as any[]) for(let i = 0; i