【发布时间】:2018-04-17 05:51:33
【问题描述】:
我正在为我的客户端应用程序使用 Angular 4。
customer.service 中的 getCustomer() 函数调用 API 来获取数据。这个函数是可观察的。
此函数需要访问令牌才能调用 API。并且访问令牌可以通过auth.service中的getAccessToken()函数获取。
但是 getAccessToen() 是异步的。我们如何从异步函数中获取价值?
请注意,getCustomer() 必须是 Observable,以便我可以映射来自响应的数据并绑定到 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.
【问题讨论】:
-
我认为更好的设计模式是设置一个 HTTP 拦截器,该拦截器在任何 HTTP 调用上设置令牌(如果客户端不存在,则创建一个新的 HTTP cal 以获取令牌) .
-
非常感谢,@AJT_82。我正在使用 flatMap,它现在可以工作了。
标签: angular angular-http-interceptors