import { ChangeDetectorRef } from '@angular/core' ; import { InstanceWithMetadata , Node } from '../../tree' ; export enum ComponentLoadState { Idle , Received , Loading , Failed } class CachedValue { constructor ( public state , public value ) { } } class LookupError { constructor ( public error ) { } } export class ComponentInstanceState { constructor ( private changeDetector ) { } private map = new Map < string , LookupError | CachedValue > ( ) ; has ( node ) { return this . map . has ( node . id ) ; } loadingState ( node ) { if ( node == null ) { return null ; } const cache = this . map . get ( node . id ) ; if ( cache == null || cache instanceof LookupError ) { return ComponentLoadState . Failed ; } return ( < CachedValue > cache ) . state ; } componentInstance ( node ) { if ( node == null ) { return null ; } const cache = this . map . get ( node . id ) ; if ( cache == null || cache instanceof LookupError ) { return null ; } const existing = < CachedValue > cache ; switch ( existing . state ) { case ComponentLoadState . Failed : return null ; case ComponentLoadState . Received : return existing . value ; case ComponentLoadState . Loading : return existing . value ; default : throw new Error ( `Unknown state: ${ existing . state }` ) ; } } wait ( node , promise ) { const previouslyCached = this . componentInstance ( node ) ; this . map . set ( node . id , new CachedValue ( ComponentLoadState . Loading , previouslyCached ) ) ; promise . then ( response => { this . map . set ( node . id , new CachedValue ( ComponentLoadState . Received , response ) ) ; this . changeDetector . detectChanges ( ) ; } ) . catch ( error => { this . map . set ( node . id , new LookupError ( error ) ) ; this . changeDetector . detectChanges ( ) ; } ) ; } reset ( identifiers ? ) { if ( identifiers == null || identifiers . length === 0 ) { this . map . clear ( ) ; } else { for ( const id of identifiers ) { this . map . delete ( id ) ; } } } }