问题
I have a component that relies on an API response for its content. I have set up the resolver but it still returns before my data is ready.
How can I make my pull_categories()
function wait until the response body is received and then return? Rather than returning an empty object because it won't wait or even call it in my case below.
service.ts
private _categories = [];
constructor(private http: HttpClient) { }
pull_categories() {
this.http.post('https://myapi.com/something', null)
.subscribe(
data => {
this._categories = data['response'];
return this._categories;
}
);
}
component.ts
categories = [];
constructor(private route: ActivatedRoute) { }
ngOnInit() {
this.route.data.subscribe(
(data: Data) => {
this.categories = data.categories;
}
);
}
resolver.ts
constructor(private categoriesService: CategoriesService) { }
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<any> | Promise<any> | any {
return this.categoriesService.pull_categories();
}
app-routing.module.ts
{
path: '',
component: HomeComponent,
resolve: {categories: CategoriesResolverService}
}
回答1:
First thing, in service.ts you don't need to subscribe, You should subscribe where you want to actually consume the data. subscribe
method returns Subscription
, not the response from the http api.
You can update your service method as
pull_categories(): Observable<any> {
return this.http.post('https://myapi.com/something', null);
}
pull_categories
method will return immediately with an Observable
, when you subscribe on it in your component (or anywhere), http call will be executed and response will be returned in your subscribe
section.
回答2:
You're returning a Subscription
from your service (and thus your resolver), instead of returning an Observable. Don't subscribe in services. And specify return values, to avoid shooting yourself in the foot:
getCategories(): Observable<Array<Category>> {
return this.http.get<Something>('https://myapi.com/something').pipe(
map(something => something.response)
);
}
Note
- the respect for naming conventions
- the usage of GET to... get data, instead of POST
- that the method defines what it actually returns
- the usage of the generic overload of the HttpClient.get() method, which allows specifying the expected type of the response body
- that having an instance fields in the service is wrong (and unnecessary).
Read the HttpClient guide, and the RxJS quide.
回答3:
Another way to get data from your backend is rather than subscribing to the data, you may also return back a promise and then use async await in your component
pull_categories(): any {
return this.http.post('https://myapi.com/something', null).toPromise();
}
This will return back a promise to your component where you can also use in the following way:
async getCategories() {
try {
const categories = await this.service.pull_categories();
} catch (e) {
}
}
来源:https://stackoverflow.com/questions/55442164/how-to-return-httpclient-response-body-from-a-request