import nanoid from 'nanoid' ; function isPromise ( value ) { return Promise . resolve ( value ) === value ; } type ProcessingJobsMap = Map < string , Promise < any > > ; const processingJobsMap = new Map ( ) ; export function asyncMerge < T extends ( ... args : any [ ] ) => any > ( fn ) { const prefix = nanoid ( ) ; const run = ( ... args ) : any => { const jobKey = prefix + '/' + JSON . stringify ( args ) ; const processingJob = processingJobsMap . get ( jobKey ) ; if ( processingJob ) { return processingJob ; } const result = fn ( ... args ) ; if ( ! isPromise ( result ) ) { return result ; } const job = result ; processingJobsMap . set ( jobKey , job ) ; const clean = ( ) : void => { processingJobsMap . delete ( jobKey ) ; } ; job . then ( clean ) . catch ( clean ) ; return job ; } ; return run as unknown as T ; }