Angular Behavior Subject on订阅事件/延迟加载api数据

Angular Behavior Subject on订阅事件/延迟加载api数据,angular,hateoas,behaviorsubject,Angular,Hateoas,Behaviorsubject,我试图在Angular 5中实现HATEOAS api数据的延迟加载。让我们假设我有一个类Car,它包含对Engine实例的引用,但是只有当引擎被访问时才应该加载它 A类汽车: export class Car { private _engine = new BehaviorSubject<Engine>(null); engine = _engine.asObservable() constructor( private enginesSe

我试图在Angular 5中实现HATEOAS api数据的延迟加载。让我们假设我有一个类
Car
,它包含对
Engine
实例的引用,但是只有当引擎被访问时才应该加载它

A类
汽车

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

    constructor(
        private enginesService
    ) {}
}
通过组件变量
Car
访问
Car
实例的一些模板,该组件变量异步访问可观察的引擎:

<div *ngIf="car.engine | async; let engine; else loadingEngine">
    <p>{{engine.type}}</p>
</div>
<ng-template #loadingEngine>Loading engine...</ng-template>
但是,当在模板中使用该方法时,它被反复调用,导致许多api请求,导致浏览器崩溃

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

编辑:

把我带到寒冷的地方。我更新了我的
汽车
实现,将发动机作为冷态可观察设备提供。现在,汽车甚至不需要知道引擎是否被访问,它只提供一次可观察的内容,每次订阅都会触发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
    ) {}
}
出口级轿车{
专用引擎:引擎;
引擎:可观察=新可观察(观察者=>{
EngineService.getEngine().subscribe(引擎=>{
这个。_发动机=发动机;
观察者:下一步(本发动机);
}
})
建造师(
私人引擎服务
) {}
}

HttpClient返回冷可观察对象(只有在有人订阅时才会执行任何操作),因此您不需要在车内订阅api调用,api调用只会在需要时发生。您只需通过
shareReplay()
将可观察对象传递给模板,这样就只有一个api请求。请尝试:

engine$:Observable<Engine> = this.enginesService.getEngine().pipe(shareReplay(1))

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

编辑:完整堆栈闪电战示例:

每次调用engine()时,是否可以将
引擎服务的实现您订阅了一个新的可观察对象。这就是导致浏览器崩溃的原因。您需要更改浏览器的实现component@Ricardo感谢您指出这一点,我没有注意到每次调用
enging()
方法时我都在实例化一个新的可观察对象是这里的关键。我不能只是从HttpClient传递observable,因为服务首先处理结果、检查状态代码、处理JSON等。但是我更改了
Car
实现,使其具有冷引擎observable。我更新了问题。为什么不在map()中进行所有处理?它不会引起可观察到的热。从我对您的评论的理解来看,您可以在
Car
内部实现map来处理来自
HttpCient
的响应。但是
Car
不必担心如何处理引擎api调用、处理错误等。对于松散耦合和强内聚性,它应该只处理把所有与
引擎
相关的东西都放在
引擎服务
上。否则,我必须在使用
引擎
的每个类中重新实现map()。是的,车里没有映射,总是在服务中映射,所以消费者可以看到随时可用的数据(这仍然是一个冷数据):)看看我会怎么做。通过控制台,您可以看到shareReplay如何缓存引擎,即使您多次关闭/打开引擎盖:
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
    ) {}
}
engine$:Observable<Engine> = this.enginesService.getEngine().pipe(shareReplay(1))

<div *ngIf="car.engine$|async as engine">...