Reputation: 43
i have a API which return JSON data of posts. I am trying to fetch these data from Angular 5 with this approach.
I declare a Post interface
export interface Post {
userId:number;
id:number;
title:string;
body:string
}
and my post.service.ts file
import { Injectable } from '@angular/core';
import {Post} from './post';
import { HttpClient, HttpHeaders, HttpResponse } from '@angular/common/http';
import { Observable } from 'rxjs';
import { catchError, map, tap } from 'rxjs/operators';
const httpOptions = {
headers: new HttpHeaders({ 'Content-Type': 'application/json' })
};
@Injectable()
export class PostService {
private posturl = 'http://jsonplaceholder.typicode.com/posts/';
constructor(private http:HttpClient) {
}
getData():Observable<Post[]> {
return this.http.get<Post[]>(this.posturl)
.pipe(
catchError(this.handleError())
);
}
}
but in service file i am getting following error. like 'Observable<{}>' is not assignable to type.....
Upvotes: 2
Views: 2795
Reputation: 1751
Map will create new observable so that you can process the response before sending it to component.you can process as follow
public getData(){
return this.http.get('http://jsonplaceholder.typicode.com/posts/')
.map((response: Response) => {
return response.json().map(this.transformData);
})
.catch((error: Response) => { return Observable.throw('Something went wrong');})
.subscribe(data => console.log(data),
(error)=> console.log('err'));
}
public transformData(r:any): Post{
let postData = <Post>({
userId : r.userId,
id: r.id,
title: r.title,
body: r.body
});
return postData;
}
.catch is added if server throws any error you can log it specifically with custom message. By using transformData()
method data will be transformed
Upvotes: 0
Reputation: 3263
You first need to map the response and convert it from JSON into plain JS/TS objects/classes. This could look something like this
getData():Observable<Post[]> {
return this.http.get<Post[]>(this.posturl)
.map((resonse) => {
return response.json().map((entry): Post => {
// convert your stuff here and return proper type
const result: Post = {
userId: result.userId,
id: result.id,
title: result.title,
body: result.body,
};
return result;
})
})
.subscribe((result) => {
console.log(result);
});
}
Note: Don't forget to import the map function
import 'rxjs/add/operator/map';
Edit: Updated my answer with proper conversion. For Interfaces it is pretty straight forward and you could even directly cast it. (Still I prefer to use the explicit way to ensure only right properties will stay and not some unwanted accidentally get passed along. For classes this is even better, then you could add new Class() and return this and your response will always have classes.
Second Note: This assumes your json result is an array. Otherwise the .json().map() won't work and you don't need it. I'd suggest to debug response.json() to have a better idea of whats being returned :)
Upvotes: 0
Reputation: 63
Your issue is with your usage of the catchError operator. But I dont think you need it anyway. If you subscribe to your Observable and an error occurs, you will already get the correct error message from the backend.
To get the data from your backend write your method as follows:
public getData(): Observable<Post[]> {
return this.http.get<Post[]>(this.posturl);
}
Then to use this data use the subscribe function of the returned observable, like this:
this.getData().subscribe(data => this.handleData(data), error => this.handleError(error));
Upvotes: 3