Save response from api service call

I am trying to wrap a http service in angular 2 with this code:

@Injectable()
export class HttpSuperService {
    private baseUrl: string;
    constructor(private http: Http) {
    }

    get(url: string): Observable<string> {
        return (
            this.baseUrl ? 
            Observable.of(this.baseUrl) :
            this.http.get('/config/').map((res: Response) => res)
        )
        .flatMap((res: any) => {
            this.baseUrl = res._body;
            return this.http.get(this.baseUrl + url)
                .map((res2: Response) => res2.json());
        });
    }
}

      

What I'm trying to do is make the first request to get the baseUrl for the application (the API is in a different url), but only makes this request once (the first time).

it works with the first request, but the second request (IE when another component uses the same service) doesn't work because something is wrong with "Observable.of". I get that I need to use Response in some way instead of a string ... This got me started thinking about this approach. Is there a better way to do this?

This solution works, but looks a bit like a verbose one, as I plan on adding other methods (POST, PUT) to this service:

@Injectable()
export class HttpSuperService {
private baseUrl: string;
constructor(private http: Http) {
}

get(url: string): Observable<string> {
    if (this.baseUrl) {
        return this.http.get(this.baseUrl + url).map((res2: Response) => res2.json());
    }
    return this.http.get('/config/').map((res: Response) => res)
        .flatMap((res: any) => {
            this.baseUrl = res._body;
            return this.http.get(this.baseUrl + url).map((res2: Response) => res2.json());
        });
    }
}

      

+3


source to share


2 answers


You can define a dependency on the lookup API URL in a dedicated method. This method can also handle some of the intermediate steps, such as URL concatenation, to further reduce duplication.

For example:

import {Http} from '@angular/http';
import {Inject} from '@angular/core';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/mergeMap';
import 'rxjs/add/observable/fromPromise';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/mapTo';
import 'rxjs/add/operator/do';

let baseUrl: string;

@Inject export class HttpSuperService {
  routeUrl(url: string) {
    return baseUrl
      ? Observable.of(baseUrl + url)
      : this.http.get('/config/')
        .do(response => baseUrl = response.text())
        .mapTo(baseUrl + url);
  }

  constructor(readonly http: Http) {}

  get(url: string): Observable<string> {
    return this.routeUrl(url)
      .flatMap(this.http.get)
      .map(res => res.json());
  }

  post(url: string, body: Something): Observable<Something> {
    return this.routeUrl(url)
      .flatMap(url => this.http.post(url, body))
      .map(response => <Something>response.json());
  }
}

      



I think this is reasonable, but we can do better, we can be DRY (there is no such thing as too dry :)):

@Inject export class HttpSuperService {
  constructor(readonly http: Http) {}

  routeUrl(url: string) {
    return baseUrl
      ? Observable.of(baseUrl + url)
      : this.http.get('/config/')
        .do(response => baseUrl = response.text())
        .mapTo(baseUrl + url);
  }

  request<R>(url: string, makeRequest: (url: string, body?: {}) => Observable<Response>) {
    return this.routeUrl(url)
      .flatMap(url => makeRequest(url))
      .map(response => <R>response.json());
  }

  get(url: string): Observable<string> {
    return this.request<string>(url, fullUrl => this.http.get(fullUrl));
  }

  post(url: string, body: Something): Observable<Something> {
    return this.request<Something>(url, fullUrl => this.http.post(fullUrl, body));
  }
}

      

I'm not entirely happy with the handling of URLs, and I'll likely refactor it further, but we've reduced the duplication significantly.

0


source


I always use this method and works great for me, hopefully it will be helpful:

in my service file:

getSomething(){
    return this._http.get('YOUR-API-ENDPOINT').map(res=> res.json());
}

      



and in my component i use this to subscribe to the Observable

return this._myServiceName.getSomething().subscribe(data =>{
  this.muyData=data;
}

      

-1


source







All Articles