import { noop , Observable } from "rxjs" ; import shareLatest from "../internal/share-latest" ; import { BehaviorObservable } from "../internal/BehaviorObservable" ; import { useObservable } from "../internal/useObservable" ; import { SUSPENSE } from "../SUSPENSE" ; import { EMPTY_VALUE } from "../internal/empty-value" ; import { useSubscription } from "../Subscribe" ; param getObservable remarks export default function connectFactoryObservable < A extends [ ] , O > ( getObservable , defaultValue ) { const cache = new NestedMap < A , BehaviorObservable < O > > ( ) ; const getDefaultValue = ( typeof defaultValue === "function" ? defaultValue : ( ) => defaultValue ) as ( ... args : A ) => O ; const getSharedObservables$ = ( input ) : BehaviorObservable < O > => { for ( let i = input . length - 1 ; input [ i ] === undefined && i > - 1 ; i -- ) { input . splice ( - 1 ) ; } const keys = [ input . length , ... input ] as any as A ; const cachedVal = cache . get ( keys ) ; if ( cachedVal !== undefined ) { return cachedVal ; } const sharedObservable$ = shareLatest ( new Observable < O > ( ( observer ) => getObservable ( ... input ) . subscribe ( observer ) ) , getDefaultValue ( ... input ) , false , ( ) => { cache . delete ( keys ) ; } ) ; const publicShared$ = new Observable < O > ( ( subscriber ) => { const inCache = cache . get ( keys ) ; let source$ = sharedObservable$ ; if ( ! inCache ) { cache . set ( keys , result ) ; } else if ( inCache !== publicShared$ ) { source$ = inCache ; publicShared$ . gV = source$ . gV ; } return source$ . subscribe ( subscriber ) ; } ) as BehaviorObservable < O > ; publicShared$ . gV = sharedObservable$ . gV ; const result = publicShared$ ; cache . set ( keys , result ) ; return result ; } ; const useSub = defaultValue === EMPTY_VALUE ? useSubscription : noop ; return [ ( ... input ) => useObservable ( getSharedObservables$ ( input ) , useSub ( ) as any ) , ( ... input ) => getSharedObservables$ ( input ) , ] ; } class NestedMap < K extends [ ] , V extends Object > { private root : Map < K , any > ; constructor ( ) { this . root = new Map ( ) ; } get ( keys ) { let current = this . root ; for ( let i = 0 ; i < keys . length ; i ++ ) { current = current . get ( keys [ i ] ) ; if ( ! current ) return undefined ; } return current ; } set ( keys , value ) { let current = this . root ; let i ; for ( i = 0 ; i < keys . length - 1 ; i ++ ) { let nextCurrent = current . get ( keys [ i ] ) ; if ( ! nextCurrent ) { nextCurrent = new Map < K , any > ( ) ; current . set ( keys [ i ] , nextCurrent ) ; } current = nextCurrent ; } current . set ( keys [ i ] , value ) ; } delete ( keys ) { const maps = [ this . root ] ; let current = this . root ; for ( let i = 0 ; i < keys . length - 1 ; i ++ ) { maps . push ( ( current = current . get ( keys [ i ] ) ) ) ; } let mapIdx = maps . length - 1 ; maps [ mapIdx ] . delete ( keys [ mapIdx ] ) ; while ( -- mapIdx > - 1 && maps [ mapIdx ] . get ( keys [ mapIdx ] ) . size === 0 ) { maps [ mapIdx ] . delete ( keys [ mapIdx ] ) ; } } }