2017-06-18 187 views
0

我正在學習Angular,並且作爲其中的一部分,我試圖瞭解如何實現我想到的用例。在這一點上,我試圖測試服務器通信。即,RxJs的可觀察物。如何在發送用戶請求之前注入HTTP請求

我記住的用例是發送POST請求,該請求需要在服務器端接受X-XSRF-TOKEN標頭。這是首次發送GET請求時作爲cookie返回給客戶端的安全首部。換句話說,與服務器的對話不能以POST請求開始。

我希望能實現,這是通過包裝角的Http類方式:

import {Http, RequestOptions, RequestOptionsArgs, Response} from '@angular/http'; 
import { Injectable} from '@angular/core'; 
import { Observable } from 'rxjs/Observable'; 
import { CookieService } from 'angular2-cookie/services/cookies.service'; 

@Injectable() 
export class RestClient { 
    private static xsrfTokenCookie: string = 'XSRF-TOKEN'; 
    private static xsrfTokenHeader: string = 'X-XSRF-TOKEN'; 
    private static xsrfToken: string = null; 

    constructor(private http: Http, private cookies: CookieService) {} 

    get(url: string, options?: RequestOptionsArgs): Observable<Response> { 
    return this.http.get(url, options); 
    } 

    post(url: string, body: any, options?: RequestOptionsArgs): Observable<Response> { 
    if (!options) { 
     options = new RequestOptions(new Headers()); 
    } 
    if (!RestClient.xsrfToken) { 
     RestClient.xsrfToken = this.cookies.get(RestClient.xsrfTokenCookie); 
    } 
    if (!RestClient.xsrfToken) { 
     //TODO: Somehow construct an Observable object which once subscribed, it will make a GET request 
     // then using the returned cookie, it will construct the actual POST request. 
    } 
    } 
} 

所以我的問題是,我怎麼能撰寫這首先發送GET請求POST請求,等待其響應然後它會發送實際的POST請求。當然,post方法的調用者將得到的返回的Observable屬於POST請求,而不是GET請求。所以如果我寫:

restClient.post('/', {}).subcribe(response => { 
    //It's POST's response 
}) 

回答

1

使用mergeMap

post(url: string, body: any, options?: RequestOptionsArgs): Observable<Response> { 
     if (!options) { 
      options = new RequestOptions(new Headers()); 
     } 
     if (!RestClient.xsrfToken) { 
      RestClient.xsrfToken = this.cookies.get(RestClient.xsrfTokenCookie); 
     } 
     if (!RestClient.xsrfToken) { 
      return this.getToken(...) 
       .mergeMap(token => this.postToServer(...)); 
     } 
     } 
    } 

在這種情況下,getToken可能是一個私人方法,返回與令牌值Observable。這同樣適用於postToServer,但返回類型ObservableReponse。通過創建可連接的最小聚焦方法,您可以將邏輯封裝爲多個部分,並通過將它們隱藏起來隱藏實現細節。

+0

不會使用'mergeMap'結果在最終返回的Observable流中有令牌嗎?如果是這樣,那不是我喜歡的! – Mehran

+0

不,mergeMap基本上把一個observable轉換成另一個。返回的Observable將是postToServer()中的一個。檢查https://www.learnrxjs.io/operators/transformation/mergemap.html –

1

使用flatMap。如果您希望在觸發新請求時忽略先前的請求,則可以使用switchMap。

return get(getUrl,....) 
    .switchMap(response => restClient.post(url, response.token ....) 

這將返回郵政呼叫的可觀察。