Angular is converting from HttpModule to HttpClientModule and deprecating the former, as detailed at Difference between HTTP and HTTPClient in angular 4?.
However the Angular tutorial at https://angular.io/tutorial/toh-pt6 uses HttpModule, while the Fundamentals information at https://angular.io/guide/http uses HttpClientModule as detailed at https://github.com/angular/angular/issues/19280. The comparison is made more difficult by the tutorial using an in-memory server while the Fundamentals use a real web server.
I've tried to make the switch from HttpModule to HttpClientModule in the Angular tutorial code using a real web server and gotten some parts working but other parts are not working. It seems to work to change one of the getHeroes methods in hero.services.ts from
getHeroes(): Promise<Hero[]> {
return this.http.get(this.heroesUrl)
.toPromise()
.then(response => response.json().data as Hero[])
.catch(this.handleError);
}
to
getHeroes(): Promise<Hero[]> {
return this.httpClient.get(this.heroesUrl)
.toPromise()
.then(data => data['heroes'] as Hero[])
.catch(this.handleError);
}
though there may be ways this can be improved and this version may have problems I haven't discovered yet.
But I don't see an equivalent for the search method in hero-search.service.ts
search(term: string): Observable<Hero[]> {
return this.http
.get(`api/heroes/?name=${term}`)
.map(response => response.json().data as Hero[]);
}
One should be able to dispense with map, but you can't use the same approach as above because there is an Observable instead of a Promise, and you get errors such as:
Type 'Observable<Object>' is not assignable to type 'Observable<Hero[]>'.
Has anyone converted the Heroes demo in the Angular tutorial to use HttpClientModule or knows how to convert the search code above?
While HttpClient parses the JSON response into an Object, it doesn't know what shape that object is. So you can specify what type the response will be:
return this.http
.get<{ data: Hero[] }>(`api/heroes/?name=${term}`)
.map(res => res.data);
Notice you can create interface for that:
interface ItemsResponse {
data: Hero[];
}
return this.http
.get<ItemsResponse>(`api/heroes/?name=${term}`)
.map(res => res.data);
If you doubt what type of response will be or don't want to create interface then just use any
:
return this.http
.get<any>(`api/heroes/?name=${term}`)
.map(res => res.data);
See also