问题
I am trying my first Angular 8 Crud Web app and wrote a page to list some company names from WebApi
My Service is correctly getting data and Iam able to print it on console
//Service.ts
export class CompanyService {
allCompanys: Company[]
constructor(private httpClient: HttpClient) { }
// Returns all the companys
GetAll(): Company[] {
this.httpClient.get<Company[]>('https://localhost:565656/api/company').subscribe(result => {
this.allCompanys = result;
//Shows data Sucessfully from Server :Working fine
console.log(this.allCompanys);
}, error => console.error(error));
return this.allCompanys;
}
But in my component I try to get the data at the starting of page by calling the service and assign it to local varaible it is giving undefined
///Component.ts
export class CompanyListComponent implements OnInit {
Companylist: Company[]
constructor(private route: ActivatedRoute, private router: Router, private companyService: CompanyService) { }
ngOnInit() {
this.Companylist = this.companyService.GetAll();
//This is executing before the service call is returning and returning Undefined
console.log("At Component " + this.Companylist)
}
My html look likes below and table not showing
//html
<tr *ngFor="let company of Companylist">
<td>{{company.Name}}</td>
<td>{{company.Phone}}</td>
<td>{{company.Email}}</td>
<td>{{company.Address}}</td>
< /tr>
I tried Observables also but not working.I need the variable to bind after the api is called.Can somebody advice what I am doing wrong
I had already checked the similar cases in SO and cant find something similar(may be not understanding to me)
回答1:
http request is done as asynchronous operation so will start requesting but the execution of getAll
asynchronous so will immediately get to the return statement and return what every allCompanys
has.
to solve this you need to update GetAll to return an observable
GetAll(): Observable<Company[]> {
return this.httpClient.get<Company[]>('https://localhost:565656/api/company')
}
at the component you subscribe to the getAll
this.companyService.GetAll().subscribe( result=> this.Companylist = result );
and we can simplify the above code with async pipe
Companylist$ : Observable<Company[]>;
ngOnInit(){
Companylist$ = this.companyService.GetAll();
}
template
<tr *ngFor="let company of Companylist$ | async">
...
</tr>
async pipe subscribes to the observable and returns the latest value it has emitted.
🌟 another way is to use async/await
, so we need to update GetAll
to return a promise and it is very easy to convert observable to promise with toPromise method
GetAll(): Promise<Company[]> {
return this.httpClient.get<Company[]>('https://localhost:565656/api/company')
.toPromise(); // 👈
}
componnet
async ngOnInit() {
this.Companylist = await this.companyService.GetAll();
...
}
read more about it here 👉 async/await
回答2:
The problem is because you are returning this.allCompanys
before async call this.httpClient.get<Company[]>('https://localhost:565656/api/company')
gets resolved.
You can either return an Observable Company[] like return this.httpClient.get('https://localhost:565656/api/company') and catch it in your view like allCompanys | async
or you could remove that return Company[] type from your method and replace it for a void, remove the return and let this.allCompanys = result
like it is in the subscription so you could also control it's value (when it gets resolved) like if (this.allCompanys) { // Do something }
回答3:
Easiest code for you to understand
In your component ts:
ngOnInit() {
// callback gets executed when your service gets the response in the API call
const callback = function(companyList: Company[]) {
this.Companylist = companyList;
}
this.companyService.GetAll(callback);
console.log("At Component " + this.Companylist)
}
In your service ts:
GetAll(callback?: Function) {
this.httpClient.get<Company[]>('https://localhost:565656/api/company').subscribe(result => {
this.allCompanys = result;
//Shows data Sucessfully from Server :Working fine
console.log(this.allCompanys);
if(callback) {
callback(this.allCompanys);
}
}, error => console.error(error));
}
回答4:
In the service, this.allCompanys
is returned synchronously even before you get the response. So it returns Undefined
. But when the response comes, the component no longer checks the update.
So You need to update the value asynchronously.
GetAll(): Company[] {
return this.httpClient.get<Company[]>('https://localhost:565656/api/company');
}
in component
this.companyService.GetAll().subScribe((res) => {
this.Companylist = res;
}, error => console.error(error)
)
来源:https://stackoverflow.com/questions/59171532/wait-for-service-api-call-to-complete-in-angular-8