Angular 4 - 如何从另一个http请求中的http请求同步获取值?

时间:2017-11-04 17:48:53

标签: angular angular-http-interceptors

我在我的客户端应用程序中使用Angular 4。

customer.service中的getCustomer()函数调用API来获取数据。这个功能是Observable。

此功能需要访问令牌才能调用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 || "";
            });                     
    }
}
&#13;
&#13;
&#13;

customer.service.ts

&#13;
&#13;
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;
    }
}
&#13;
&#13;
&#13;

客户detail.component.ts

&#13;
&#13;
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.
&#13;
&#13;
&#13;

2 个答案:

答案 0 :(得分:0)

在我的customer.service.ts中,您可以使用以下内容链接方法调用:

getCustomer(id: string): Observable<CustomerResource> {
  this.authService.getAccessToken()
    .map((accessToken) => { 
      let headers = addAccessTokenToHeader(accessToken);

      let url = `${this.customersUrl}/${id}`;
      return this.http.get(url, { headers: headers })
        // rest of the code
      }); 

如果它不起作用,请尝试将.map替换为.switchMap

答案 1 :(得分:0)

我正在使用flatMap,现在可以使用了。非常感谢您的建议@ AJT_82