If I understood you correctly, basically what you are looking for is a way to cancel "old" rest-calls, as soon as a new item is selected -> the rxjs-way would be to utilize an .takeUntil(...)
SomeObjectComponent implements OnDestroy {
// to clean up any open subscriptions it is helpful to have a destroy-event
private destroyed$: Subject<any> = new Subject<any>();
// your vars
someObject: SomeObject;
extraData: ExtraData;
@Input()
set item(v: SomeObject) {
this.someObject = v;
this.loadExtraData$.next(v.id);
}
// a trigger to load extra data
private loadExtraData$: Subject<number> = new Subject<number>(); // type "number" is just an assumption, this can be whatever type "v.id" is
// the stream to load extra data
private extraData$: Observable<any> = this.loadExtraData$
.takeUntil(this.destroyed$) // when the component is destroyed this will ensure that any open subscription will be closed as well to prevent memory leaks
.switchMap(id => {
return this.backendService
.getExtraData(id)
.takeUntil(this.loadExtraData$); // will discard the rest-call the next time loadExtraData$ is triggered (if it is still running)
})
.do(extraData => this.extraData = extraData) // if you only need the data in the template, then don't use this line and use the "| async"-pipe instead
.share();
// this is called by the angular2-lifecycle, when the component is removed
ngOnDestroy() {
this.destroyed$.next();
}
}
If you just need the extra data in the template, then you might want to use the async
-pipe:
<span>Some extra data: {{(extraData$ | async)?.someAttribute}}</span>
As a small side-note and slightly off-topic: It is a better practice to not load the extra data within the component, but outside of the component and use an @Input()
for the extra-data, for a number of reasons:
- testability is much more efficient and easier to achieve if components are encapsulated and don't rely on any service or other components
- especially with rest-calls there is a danger of making redundant requests if a component is added twice e.g.
- components are much easier to reuse in different contexts if they just have
@Input()
s and @Output()
s
That being said, without knowing your current architecture, this might bear bigger refactoring that might not be worth the time, but it is something to keep in mind for future applications.