角度行为主题订阅事件/延迟加载 api 数据



我正在尝试在 Angular 5 中实现 HATEOAS API 数据的延迟加载。假设我有一个类Car,其中包含对Engine实例的引用,但引擎只有在被访问时才应加载。

A类Car

export class Car {
private _engine = new BehaviorSubject<Engine>(null);
engine = _engine.asObservable()
constructor(
private enginesService
) {}
}

A类Engine

export class Engine {
type: string;
}

一些模板可以通过组件变量访问Car的实例car,异步访问可观察到的引擎:

<div *ngIf="car.engine | async; let engine; else loadingEngine">
<p>{{engine.type}}</p>
</div>
<ng-template #loadingEngine>Loading engine...</ng-template>

上面,汽车不知道何时访问engine,也不知道发动机必须从 API 加载。现在我尝试仅通过 getter 方法提供对 Car.engine 的访问,该方法将返回car.asObservable()并触发 api 请求,如下所示:

export class Car {
private _engine = new BehaviorSubject<Engine>(null);
constructor(
private enginesService
) {}
engine(): Observable<Engine> {
this.enginesService.getEngine().subscribe( engine => {
_engine.next(engine);
)
return _engine.asObservable()
}
}

但是当在模板中使用该方法时,它被一遍又一遍地调用,导致许多 api 请求,导致浏览器崩溃。

我的想法是将BehaviorSubject包装在一个提供onSubscribe事件的类中。Car可以订阅onSubscribe事件,并知道何时有东西试图获取引擎值。有没有其他方法可以知道何时访问engine

编辑:

Funkizer把我带到了冷冰冰的可观察物。我更新了我的Car实现,以将引擎作为冷可观察对象提供。现在汽车甚至不需要知道引擎是否被访问,它只需要提供一次可观察的,每个订阅都会触发 api 调用:

export class Car {
private _engine: Engine;
engine: Observable<Engine> = new Observable( observer => {
enginesService.getEngine().subscribe( engine => {
this._engine = engine;
observer.next(this._engine);
}
})
constructor(
private enginesService
) {}
}

HttpClient 返回冷可观察量(只会在有人订阅时执行任何操作),因此您无需在 Car 中订阅 api 调用,并且 api 调用只会在需要时发生。只需通过shareReplay()将可观察量传递给模板,因此只有一个 api 请求。尝试:

engine$:Observable<Engine> = this.enginesService.getEngine().pipe(shareReplay(1))
<div *ngIf="car.engine$|async as engine">...

编辑:全栈闪电战示例:https://stackblitz.com/edit/angular-ea52a7?file=app%2Fapp.component.html

最新更新