I'm using Angular 4 for my client application.
The getCustomer() function in customer.service calls an API to get data. This function is Observable.
This function needs an access token to be able to call the API. And the access token can be gotten from getAccessToken() function in auth.service.
But getAccessToen() is async. How can we get value from the async function?
Note that getCustomer() must be Observable so that I can map data from response and bind to members of customer.component.
auth.service.ts
import { Injectable } from '@angular/core';
import { Http, Headers } from '@angular/http';
import { Observable } from 'rxjs/Observable';
@Injectable()
export class AuthService {
private tokenEndpoint = "http://localhost:9000/connect/token";
private clientId = "testclientid";
private clientSecret = "testsecret";
constructor(private http: Http) { }
getAccessToken() : Observable<any> {
let credential = "Basic " + btoa(`${this.clientId}:${this.clientSecret}`);
let body = "grant_type=client_credentials&scope=testscope";
let headers = new Headers();
headers.set("Content-Type", "application/x-www-form-urlencoded");
headers.set("Authorization", credential);
return this.http.post(this.tokenEndpoint, body, { headers: headers })
.map(result => {
let data = result.json();
return data.access_token || "";
});
}
}
customer.service.ts
import { Injectable } from '@angular/core';
import { Http, Headers } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import { Customer } from './customer';
import { Address } from './customer';
import { ResourceData } from './customer';
import { ResourceAttributes } from './customer';
import { CustomerResource } from './customer';
import { ResourceCollection } from './customer';
import { AuthService } from '../auth/auth.service';
@Injectable()
export class CustomerService {
private customersUrl = "http://localhost:60001/api/v1/customers";
constructor(private http: Http, private authService: AuthService) { }
getCustomer(id: string): Observable<CustomerResource> {
let accessToken = this.authService.getAccessToken().subcribe(
// how to get accessToken from authService because subcribe is async?
);
let headers = addAccessTokenToHeader(accessToken);
let url = `${this.customersUrl}/${id}`;
return this.http.get(url, { headers: headers })
.map(result => {
return result.json() as CustomerResource;
})
.catch((error) => {
console.log(error);
return Observable.throw(error);
});
}
private addAccessTokenToHeader(accessToken: string): Headers {
let headers = new Headers();
headers.set("Authorization", `Bearer ${accessToken}`);
return headers;
}
}
customer-detail.component.ts
showCustomer(id: string) {
this.modalTitle = "Update PL customer";
this.buttonSaveTitle = "Update";
this.customerService.getCustomer(id)
.subscribe(customer => {
this.mapFromResource(customer.data);
this.customerModal.show();
});
}
private mapFromResource(data: ResourceData) {
this.customerId = data.id;
this.reference = data.attributes.reference;
this.lastName = data.attributes.lastName;
this.middleName = data.attributes.middleName;
this.firstName = data.attributes.firstName;
}
// this.customerId, this.reference are the members of customer.component. They are binding on UI.