My Angular 4 / TypeScript 2.3 service has a method called build()
that throws an error if a certain property is not initialized. I am attempting to create a safer alternative called safeBuild()
that will return an Observable and wait for the property to be initialized before executing build()
export class BuildService {
renderer:Renderer2; // must be set for build() below to work
// emits the new Renderer2 when renderer is set
private rendererSet$:BehaviorSubject<Renderer2> = new BehaviorSubject(null);
/** Set renderer, and notify any listener */
setRenderer(renderer:Renderer2){
this.renderer = renderer;
this.rendererSet$.next(renderer);
}
/** Returns a new DOM element. Requires renderer to be set */
build(elemTag:string){
// if renderer is not set, we can't proceed
// why is this error thrown when safeBuild() is called?
if (!this.renderer)
throw new Error('Renderer must be set before build() is run');
return this.renderer.createElement(elemTag);
}
/**
* A safe version of build(). Will wait until renderer is set
* before attempting to call build (Asynchronous)
*/
safeBuild(elemTag:string):Observable<any> {
// inform user that renderer should be set
// this warning is printed to the console as expected
if (!this.renderer)
console.warn('The build will be delayed until setRenderer() is called');
// Listen to rendererSet$, filter out the null output, and call build()
// only once the renderer is set. Why does the error still get thrown?
return Observable.concat(
this.rendererSet$.filter(e=>!!e).take(1),
Observable.of(this.build(elemTag))
)
}
}
I try to execute the build like this (from another service):
this.buildService.safeBuild(elemTag).subscribe(...)
In the console I see:
Warning: The build will be delayed until setRenderer() is called
Error: Renderer must be set before build() is run
I expected the warning, but then nothing to happen until another part of my app calls setRenderer()
. At that point, the code in subscribe()
would run.
But why am I still encountering the error?