Reputation: 23
I have this method in my service.
get trucks() {
if (!this.cache$) {
this.cache$ = this.requestAvailableTrucks().pipe(
shareReplay(CACHE_SIZE)
);
}
return this.cache$;
}
private requestAvailableTrucks() : Observable<Array<any>> {
return this.http.get<any>(API_ENDPOINT_TRUCKS).pipe(
map(response => response.value)
);
}
In my app component I need to initialized my property as the result from the requestAvailableTrucks call. And after that I need to do some logic depending on the result that came from the backend. But the problem is that I don't know how can I await this method.
When I try
ngOnInit() {
this.locations = this.truckService.trucks;
... The other logic ...
}
the other logic don't wait for the method in my service to end.
The only think that can be done is the approach with subscribe, and to put the code there but I need to have my logic in my service and call it from my ts.file like this
Upvotes: 2
Views: 111
Reputation: 149
If you want to use await, an easy way is to convert observable to be promise.
async ngOnInit() {
this.trucks = await this.truckService.trucks.toPromise();
// other logics
}
You can actually convert every observable api call to be promise, then you will be able to forget everything about stream. Just think in regular promise ways.
For a more reactive way:
class TruckService {
trucks$ = this.requestAvailableTrucks().pipe(
shareReplay(CACHE_SIZE)
);
requestAvailableTrucks() {...}
}
tracks$ = this.truckService.tracks$;
ngOnInit() {....}
// TEMPLATE
{{tracks$ | async}}
Upvotes: 0
Reputation: 355
you can simply use subscribe so that it will wait for the response.
ngOnInit() {
this.truckService.trucks.subscribe(trucks => {
this.locations = trucks;
});
}
Upvotes: 1
Reputation: 14750
You can use the .pipe()
method on an observable stream to modify the values as they come through. There are various pipeable operators that allow you to transform the stream. In your case, it looks like you are trying to turn a stream of "trucks array" into a stream of "location array". In that case, using the map()
operator, something like this would work:
ngOnInit() {
this.locations = this.truckService.trucks.pipe(
map(trucks => trucks.map(t => t.location))
);
}
You aren't await
ing per se, but rather transforming the values as they come through. Also, you don't need to subscribe here, but you could if you really needed to. Usually you can use the async
pipe in the template like this:
<h1>Truck Locations</h1>
<ul>
<li *ngFor="let location of locations | async">
{{ location }}
</li>
</ul>
If you needed to do some side effect type stuff in your "other logic", you may utilize the tap
operator inside the pipe()
as well.
ngOnInit() {
this.locations = this.truckService.trucks.pipe(
map(trucks => trucks.map(t => t.location)),
tap(() => this.isLoading = false)
);
}
Upvotes: 0