2017-11-04 8 views
0

クライアントアプリケーションにAngular 4を使用しています。角度4 - 別のhttpリクエストでhttpリクエストから値を同期的に取得するにはどうすればよいですか?

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 || ""; 
 
      });      
 
    } 
 
}

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> { 
 
\t \t let accessToken = this.authService.getAccessToken().subcribe(
 
\t \t \t // how to get accessToken from authService because subcribe is async? 
 
\t \t); 
 
\t \t 
 
\t \t let headers = addAccessTokenToHeader(accessToken); 
 
\t 
 
     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); 
 
      }); 
 
    }  
 

 
\t private addAccessTokenToHeader(accessToken: string): Headers { 
 
     let headers = new Headers(); 
 
     headers.set("Authorization", `Bearer ${accessToken}`); 
 

 
     return headers; 
 
    } 
 
}

顧客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.

+1

https://stackoverflow.com/questions/34104638/how-to-chain-http-calls-in-angular2 – Alex

+0

私はより良いデザインパターンはHTTPを設定することですHTTP呼び出しでトークンを設定するインターセプター(クライアント側に存在しない場合は、新しいHTTP calを作成してトークンを取得します)。 – Yani

+0

ありがとう、@ AJT_82。私はflatMapを使用しています。 –

答えて

0

私はflatMapを使用しています。現在は動作しています。どうもありがとうございます@AJT_82

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 
     }); 

それが動作しない場合は、.switchMap.mapを交換してみてください。

関連する問題