import { IterableElement } from 'type-fest' ; enum ActionTypeEnum { Filter = 'filter' , Map = 'map' , ForEach = 'forEach' , Reduce = 'reduce' , FlatMap = 'flatMap' } class Action { public static Type = ActionTypeEnum ; constructor ( public readonly type , public readonly args ) { this . type = type ; this . args = args ; } } /**
 * 异步数组，支持静态方法和链式调用
 */ export class AsyncArray < T > implements PromiseLike < T [ ] > { static reduce < T extends any [ ] , R > ( arr , fn , res ) { return arr . reduce ( ( res , item , index ) => res . then ( ( r ) => fn ( r , item , index ) ) , Promise . resolve ( res ) ) ; } static map < T , R > ( arr , fn ) { return Promise . all ( arr . map ( ( item , index ) => fn ( item , index ) ) ) ; } static async filter < T > ( arr , fn ) { const res = [ ] ; await AsyncArray . map ( arr , async ( item , index ) => { if ( await fn ( item , index ) ) { res . push ( item ) ; } } ) ; return res ; } static async flatMap < T , R > ( arr , fn ) { return ( await Promise . all ( arr . map ( ( item , index ) => fn ( item , index ) ) ) ) . flatMap ( ( r ) => r ) ; } static async forEach < T extends any [ ] > ( arr , fn ) { await AsyncArray . map ( arr , fn ) ; } private tasks : Action [ ] = [ ] ; constructor ( private readonly arr ) { } map < R > ( fn ) { this . tasks . push ( new Action ( ActionTypeEnum . Map , [ fn ] ) ) ; return this as any ; } flatMap < R > ( fn ) { this . tasks . push ( new Action ( ActionTypeEnum . FlatMap , [ fn ] ) ) ; return this as any ; } filter ( fn ) { this . tasks . push ( new Action ( ActionTypeEnum . Filter , [ fn ] ) ) ; return this ; } async forEach < R > ( fn ) { this . tasks . push ( new Action ( ActionTypeEnum . Map , [ fn ] ) ) ; await this ; } then < TResult1 = T [ ] , TResult2 = never > ( resolve ? , reject ? ) { const res = this . value ( ) ; res . then ( ( r ) => { resolve && resolve ( res as any ) ; return r ; } ) . catch ( ( e ) => { reject && reject ( e as any ) ; throw e ; } ) ; return res as any ; } private async value ( ) { let res = this . arr ; for ( const task of this . tasks ) { switch ( task . type ) { case ActionTypeEnum . Filter : res = await AsyncArray . filter ( res , task . args [ 0 ] ) ; break ; case ActionTypeEnum . Map : res = await AsyncArray . map ( res , task . args [ 0 ] ) ; break ; case ActionTypeEnum . FlatMap : res = await AsyncArray . flatMap ( res , task . args [ 0 ] ) ; break ; case ActionTypeEnum . ForEach : await AsyncArray . forEach ( res , task . args [ 0 ] ) ; return ; case ActionTypeEnum . Reduce : return await AsyncArray . reduce ( res , task . args [ 0 ] , task . args [ 1 ] ) ; } } return res ; } }