I'm trying to build an application and I don't want my component to have unnecessary code. There is a lot of logic that I would like to put in a service and then inject the service into my component. Let say my component has a variable named 'result':
my.component.ts
.....
private result:number;
and my service has an async method:
my.services.ts
......
......
getNumberFromApi(){
callAsync().subscribe( data => {
console.log('This is the data obtained..' data);
})
I would like to have the chance of passing a parameter to the method getNumberFromApi():
getNumberFromAPI(destinationVar:number){
callAsync().subscribe( data => {
console.log('This is the data obtained..' data);
destinationVar=data;
})
So that in my component I would be able to call the method of this service in this way:
my.component.ts
.....
private result:number;
myServiceInstance.getNumberFromApi(result);
I understand this is not possible (probably because the method's stack is already gone at the time the response arrives) but I don't find a way to do this or something similar. Can somebody recommend me an alternative? I would like to modify from the service variables of the component, even with async methods, without anything more than a method invocation line in the component. Is this possible? Am I missing a crucial concept of how Typescript/Angular works here? Thanks.
CodePudding user response:
You'd need to return the observable from the service and subscribe to it in the component. This way, the async nature of the observable would be preserved and you'd get to invoke the presumed API call with different parameters if needed.
Serivce
import { Observable } from 'rxjs';
getNumberFromApi(): Observable<any> {
return callAsync();
}
Component
export class SomeComponent implements OnInit {
someVar: any;
constructor(private someService: SomeService) { }
ngOnInit() {
this.someService.getNumberFromApi().subscribe({
next: (value: any) => this.someVar = value,
error: (error: any) => { }
});
}
}
On the other hand, if the variable someVar
in the component is only used in the template to render some data, you could skip the subscription in the component controller and using the async
pipe in the template.
Controller (*.ts)
import { Observable } from 'rxjs';
export class SomeComponent implements OnInit {
someVar$: Observable<any>; // <-- dollar sign is only a convention
constructor(private someService: SomeService) { }
ngOnInit() {
this.someVar$ = this.someService.getNumberFromApi();
}
}
Template (*.html)
<ng-container *ngIf="(someVar$ | async) as someVar">
<!-- use `someVar` -->
{{ someVar }}
</ng-container>