2017-06-18 140 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 ....) 

这将返回邮政呼叫的可观察。