/**
 * Use as a Decorator on async functions, it will prevent multiple 'active' calls as the same time
 *
 * If a promise was returned from a previous call to this function, that hasn't yet resolved it will
 * be returned, instead of calling the original function again
 *
 * Results are not cached, once the promise has returned, the next call will result in a fresh call
 *
 * Read more at https://github.com/bitwarden/jslib/pull/7
 */ export function sequentialize ( cacheKey ) { return ( target , propertyKey , descriptor ) => { const originalMethod = descriptor . value ; const caches = new Map < any , Map < string , Promise < any > > > ( ) ; const getCache = ( obj ) => { let cache = caches . get ( obj ) ; if ( cache != null ) { return cache ; } cache = new Map < string , Promise < any > > ( ) ; caches . set ( obj , cache ) ; return cache ; } ; return { value : function ( ... args ) { const cache = getCache ( this ) ; const argsCacheKey = cacheKey ( args ) ; let response = cache . get ( argsCacheKey ) ; if ( response != null ) { return response ; } const onFinally = ( ) => { cache . delete ( argsCacheKey ) ; if ( cache . size === 0 ) { caches . delete ( this ) ; } } ; response = originalMethod . apply ( this , args ) . then ( ( val ) => { onFinally ( ) ; return val ; } ) . catch ( ( err ) => { onFinally ( ) ; throw err ; } ) ; cache . set ( argsCacheKey , response ) ; return response ; } , } ; } ; }