import { Store } from './store' ; import { Inject , SkipSelf , Optional , OnDestroy , isDevMode , Injectable } from '@angular/core' ; import { Subscription , combineLatest } from 'rxjs' ; import { map , switchMap , tap } from 'rxjs/operators' ; import { BehaviorSubject } from 'rxjs' ; import getReduxDevToolsPlugin , { StorePlugin } from './plugins/redux_devtools' ; import { ActionState } from './action-state' ; export type StoreInstanceMap = Map < string , Store < any > > ; let rootStore ; internal @ Injectable ( ) export class RootStore { private connectSuccessed = false ; /**
     * 数据流 数据是一个Map，k,v键值对，关键字->状态数据
     */ private readonly _containers = new BehaviorSubject < StoreInstanceMap > ( new Map < string , Store < any > > ( ) ) ; private _plugin : StorePlugin = getReduxDevToolsPlugin ( ) ; private _combinedStateSubscription : Subscription = new Subscription ( ) ; constructor ( ) { if ( this . _plugin . isConnectSuccessed ( ) ) { this . connectSuccessed = true ; this . _assignCombinedState ( ) ; console . log ( `是否在Angular开发环境：${ isDevMode ( ) }, 初始化root-store` ) ; } } private _assignCombinedState ( ) { this . _combinedStateSubscription = this . _containers . pipe ( switchMap ( containers => this . _getCombinedState ( containers ) ) ) . pipe ( map ( states => { const actionName = ActionState . getActionName ( ) ; const state = states . reduce ( ( acc , curr ) => { acc [ curr . containerName ] = curr . state ; return acc ; } , < { [ key ] : any ; } > { } ) ; return { state : state , actionName : actionName } ; } ) ) . subscribe ( c => { this . _plugin . handleNewState ( c . actionName , c . state ) ; } ) ; } param containers private _getCombinedState ( containers ) { return combineLatest ( ... Array . from ( containers . entries ( ) ) . map ( ( [ containerName , container ] ) => { return container . state$ . pipe ( map ( state => ( { containerName , state } ) ) , tap ( data => { } ) ) ; } ) ) ; } internal ngOnDestroy ( ) { this . _combinedStateSubscription . unsubscribe ( ) ; } internal registerStore ( store ) { if ( ! this . connectSuccessed ) { return ; } const containers = new Map ( this . _containers . value ) ; if ( containers . has ( store . getStoreInstanceId ( ) ) ) { throw new Error ( `Store: Store with duplicate instance ID found! ${ store . getStoreInstanceId ( ) }` + ` is already registered. Please check your getStoreInstanceId() methods!` ) ; } containers . set ( store . getStoreInstanceId ( ) , store ) ; this . _containers . next ( containers ) ; } existStoreInstanceId ( instanceId ) { const containers = new Map ( this . _containers . value ) ; if ( containers . has ( instanceId ) ) { return true ; } return false ; } internal unregisterStore ( store ) { if ( ! this . connectSuccessed ) { return ; } const containers = new Map ( this . _containers . value ) ; containers . delete ( store . getStoreInstanceId ( ) ) ; this . _containers . next ( containers ) ; } } export function getSingletonRootStore ( ) { if ( ! rootStore ) { rootStore = new RootStore ( ) ; } return rootStore ; }