Masoud Motallebipour
Masoud Motallebipour

Reputation: 414

How to subscribe inside observable and return observable

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

Answers (3)

brooklynDadCore
brooklynDadCore

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

Anuradha Gunasekara
Anuradha Gunasekara

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

Buczkowski
Buczkowski

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

Related Questions