【发布时间】:2017-07-09 21:26:02
【问题描述】:
我的 Angular 4 / TypeScript 2.3 服务有一个函数build(),如果类属性未初始化,则会出错。我正在尝试构建一个更安全的版本——safeBuild()——它将返回一个 Observable,它会在尝试调用 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))
)
}
}
我尝试像这样构建(从另一个服务):
this.buildService.safeBuild(elemTag).subscribe(...)
在我看到的控制台中:
警告:构建将延迟到 setRenderer() 被调用
错误:必须在 build() 运行之前设置渲染器
我预计会收到警告,但在我的应用程序的另一部分调用 setRenderer() 之前什么都不会发生。此时,subscribe() 中的代码将运行。
为什么我会看到错误?
【问题讨论】:
-
什么时候调用 setRenderer?
-
@BunyaminCoskuner 稍后 -- 在
safeBuild()之后,来自另一个组件。 -
Observable.of(this.build(elemTag))需要调用this.build来创建 observable,这发生在 将其传递给.concat之前。 -
为什么不只是
return this.rendererSet$.filter(e => !!e).map(() => this.build());? -
@jonrsharpe 接近我自己找到的解决方案。我保留了
take(1),因为我不希望取消订阅的负担在调用代码上,我使用了switchMap(r => Observable.of(this.build()))。它可以工作,但map()更干净。我仍然想知道为什么会抛出错误。
标签: angular typescript rxjs5