Reputation: 414
I want to get result of an observable and make some changes and then return the result with type of observable again for components to subscribe. this is my code:
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/throw';
import 'rxjs/add/observable/of';
import {Observable} from 'rxjs/Observable';
get_items() {
this.http.get(this.router_url).map(res => res.json()).catch(this.handleRequestError).subscribe(
(result) => {
result = result.data[0].my_item
return Observable.of( data: [{my_items: result}]});
},
(error) => {}
)
}
the problem is in component that is using and trying to .subscribe result of get_items() they get error of : Uncaught (in promise): TypeError:
this.generalService.get_items(...).subscribe is not a function
but when I return just:
return Observable.of( data: [{my_items: result}]});
it works fine but it's not what I want any way, the result type is Observable so why I get this error? thanks in advance
Upvotes: 4
Views: 9063
Reputation: 1579
I ran into something similar, and this is how I resolved it.
FooService.ts
private fetchFoo(): Observable<any> {
return this.httpService.get('/foo');
}
public async getFoo(): Promise<Foo[]> {
if(this.foo.length === 0) {
return this.fetchFoo()
.toPromise() <-- use in place of .subscribe
.then((response) => {
this.foo = response.data;
return this.foo;
}, (err) => {
console.debug(err);
return this.foo;
});
} else {
return this.foo;
}
}
AnyComponent.ts
public getFoo(): void {
this.fooService.getFoo().then((response) => {
this.doSomething(response);
})
}
Using .toPromise
instead of .subscribe
to handle the observable will still execute the network call, and sets the exposed service function to be a promise which is thenable, instead of a subscription which would need to be unsubscribed from.
Upvotes: 1
Reputation: 6983
As angular doc says HttpClient
's get()
returns a Observable. So you dont have to create a new one.
/** * Construct a GET request which interprets the body as JSON and returns it. * * @return an `Observable` of the body as type `T`. */ get<T>(url: string, options?: { headers?: HttpHeaders | { [header: string]: string | string[]; }; observe?: 'body'; params?: HttpParams | { [param: string]: string | string[]; }; reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; }): Observable<T>;
Try this. And replace any
with the interface that represents the response;
import { Observable } from "rxjs";
get_items() Observable<any>{
return this.http.get<any>(this.router_url).map(res => res.json());
}
And in the component.
this.service.get_items().subscribe((res) => {
// request data will be here in the res
});
Upvotes: 1
Reputation: 2416
You can do something like that:
get_items() {
this.http.get(this.router_url).map(res => {
const result = res.json();
return {data: [{my_items: result.data[0].my_item}]};
});
}
The map
operator is the place where you should modify your response before actually subscribe to it.
Upvotes: 9