There is no way to turn asynchronous variable to be synchronous. The only thing you could do is to move all the statements depending on the async variable inside the subscription.
firstFunc(id) {
this.dataService.getDataById(id).subscribe(res=> {
this.data = res;
console.log('res from service', this.data);
//do something with this.data
});
}
If you need to use this.data
in multiple places and do not wish to trigger the HTTP call each time, you could cache the response in the service using RxJS ReplaySubject
and use it in the component.
Service
export class DataService {
private cachedSource = new ReplaySubject<any>(1); // <-- cache last emitted value
public cached$ = this.cachedSource.asObservable();
getDataById(id: number): Observable<Model> {
return this.httpClient.get<Model>(this.api + 'data?id=' + `${id}`).pipe(
tap(res => this.cachedSource.next(res))
);
}
}
Component
export class SampleClass implements OnDestroy {
complete$ = new Subject<any>();
firstFunc(id) {
this.getDataById(id);
this.dataService.cached$.pipe(takeUntil(this.complete$)).subscribe(
res => {
this.data = res;
console.log('res from service', this.data);
//do something with this.data
}
);
}
someOtherFunction() {
this.dataService.cached$.pipe(take(1)).subscribe(
res => { // <-- will emit the last value from the HTTP call
console.log('res from service', res);
//do something with `res`
}
);
}
getDataById(id: number) {
this.dataService.getDataById(id).subscribe(); // <-- pushes response to `this.dataService.cached$`
}
ngOnDestroy() {
this.complete$.next(); // <-- close open subscriptions
}
}