import { Pipe , PipeTransform } from '@angular/core' ; import { isObservable , Observable , of } from 'rxjs' ; import { map , startWith , catchError } from 'rxjs/operators' ; export interface AsyncState < T > { pending : boolean ; value ? : T ; error ? : any ; } param value param pendingIf function isPending < T > ( value , pendingIf ) { if ( typeof pendingIf !== 'object' ) { return value === pendingIf ; } if ( typeof value !== 'object' ) { return true ; } const props = Object . getOwnPropertyNames ( pendingIf ) ; for ( let i = 0 ; i < props . length ; i ++ ) { const propName = props [ i ] ; if ( value [ propName ] !== pendingIf [ propName ] ) { return false ; } } return true ; } /**
 * This pipe will wrap an observable onto an object which
 * will reflect its pending state, value and/or error message.
 */ @ Pipe ( { name : 'asyncState' , } ) export class AsyncStatePipe implements PipeTransform { transform < T > ( value , pendingIf = null ) { if ( ! isObservable ( value ) ) { return of ( { pending : false , value , } ) ; } return value . pipe ( map ( ( value ) : AsyncState < T > => ( { pending : typeof value === 'undefined' || isPending ( value , pendingIf ) , value , } ) ) , startWith ( { pending : true , } ) , catchError ( error => of ( { pending : false , error , } ) ) ) ; } }