I'm writing this application in Angular and I'm using Resolvers.
Once the user loads a given page, there is an API-Endpoint that will be hit by the resolver and one of the parameters that needs to be passed is the user's country. To get that info, I'm using the ip-api.com API.
Here is my problem. Because I'm using Observables, I can't get the country location on time, before the request is out. I need to have the user's country first and then send the request.
My idea was to create a service that gets injected in the root, so as soon as the application starts its constructor executes a method to fetch the user location data. Then, I store that data on a BehaviorSubject so it can be accessed by any class that needs it later.
How can I ensure that I will always have the data I need before any request goes out?
If the user comes from the main page everything works well, but if the user goes directly to a secondary page, then I get an error.
Here is what I got:
Helper Service
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { BehaviorSubject, Observable } from 'rxjs';
import { take } from 'rxjs/operators';
@Injectable( { providedIn: 'root' } )
export class HelperService {
public showRightDrawer = new BehaviorSubject<boolean>(false);
public requestCountry = new BehaviorSubject<string>(undefined);
constructor(private http: HttpClient) {
this.detectUserLocation();
}
detectUserLocation(): void {
const url = 'http://ip-api.com/json';
this.http.get(url).pipe(take(1)).subscribe((c: any) => {
const cc = c.countryCode;
this.requestCountry.next(cc);
return cc;
});
}
}
Service that hits my internal API
import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { take } from 'rxjs/operators';
import { SERVER_URL } from 'src/environments/environment';
import { HelperService } from '../common/services/helper.service';
import { Roaster } from './roaster.interface';
@Injectable()
export class RoasterService {
private endPoint: string = SERVER_URL;
private country: string;
private httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json',
responseType: 'text'
})
};
constructor(private httpService: HttpClient, private helper: HelperService) {
helper.requestCountry.subscribe((c) => this.country = c);
}
getRoasters(page?: number, limit?: number): Observable<Roaster[]> {
const reqLimit = limit || 15;
const reqPage = page || 0;
return this.httpService
.get<Roaster[]>(`${this.endPoint}roaster?limit=${reqLimit}&page=${reqPage}&country=${this.country.toLowerCase()}`, this.httpOptions )
.pipe(take(1));
}
}