簡體   English   中英

Angular2:動態同步http請求

[英]Angular2: Dynamic synchronous http requests

目標:發出一系列同步的http請求,並能夠將它們作為一個可觀察的流進行訂閱。

樣本(無效):

let query_arr = ['test1','test2','test3']

function make_request(query_arr){

    if (query_arr.length){

        let payload = JSON.stringify(query_arr[0]);
        let headers = new Headers();

        query_arr.splice(0,1);

        this.http.post('https://endpoint/post',payload,{headers:headers})
            .map((res:Response) => {make_request(query_arr)})

    }

}.subscribe(
    data => console.log('finished http request, moving on to next http request'),
    err => console.error(err),
    () => console.log('all http requests have been finished')
);

make_request(query_arr)

目標功能:

  • 需要知道每個響應何時返回
  • 必須知道所有回復何時返回

您需要利用flatMap運算符來flatMap執行請求(一個接一個)。 為此,您需要遞歸構建數據處理鏈。 這里的重點是調用上一個可觀察值(上一個請求返回的值)的運算符。

這樣,請求將在自身執行之前等待上一個請求完成。 訂閱時提供的回調將在所有請求執行后被調用。

這是此方法的示例實現:

makeRequest(queryArr, previousObservable){
  if (queryArr.length) {
    let payload = JSON.stringify(queryArr[0]);
    let headers = new Headers();
    (...)

    queryArr.splice(0,1);

    var observable = null;
    if (previousObservable) {
      observable = previousObservable.flatMap(() => {
        return this.http.post('https://testsoapi.apispark.net/v1/entities', payload,{
            headers:headers
          })
          .map((res:Response) => res.json())
          .do(() => {
            console.log('request finished');
          });
      });
    } else {
      observable = this.http.post('https://testsoapi.apispark.net/v1/entities', payload, {
        headers:headers
      })
        .map((res:Response) => res.json())
        .do(() => {
          console.log('request finished');
        });
    }

    return this.makeRequest(queryArr, observable);
  } else {
    return previousObservable;
  }
}

最初可以這樣調用此方法:

test() {
  let queryArr = [
    { val: 'test1' },
    { val: 'test2' },
    { val: 'test3' }
  ];

  this.makeRequest(queryArr).subscribe(
    () => {
      console.log('all requests finished');
    });
}

請參閱以下代碼: https ://plnkr.co/edit/adtWwckvhwXJgPDgCurQ ? p = preview。

您的代碼中還有一些語法錯誤,也需要解決。 但是除了那些之外,您可以使用concatMap + defer大大簡化。

let query_arr = ['test1','test2','test3'];
let self = this;

Rx.Observable.from(query_arr).map(JSON.stringify)
  .concatMap(payload => {
    let headers = new Headers();
    return Rx.Observable.defer(() => {
      self.http.post('https://endpoint/post',payload,{headers:headers});
    });
  }, resp => resp.json())
  .subscribe(
    data => console.log('finished http request, moving on to next http request'),
    err => console.error(err),
    () => console.log('all http requests have been finished')
  );

這樣做的基本思想是將查詢數組轉換為Observable,然后急切地創建一系列僅在訂閱后才執行的惰性請求。 但是,通過將帖子包裝在一個defer每個請求將僅在前一個請求完成時分派。

或打字稿中的非遞歸版本,其中您將一個數組提供給forkjoin

在return observableObj(res.json())中,您知道從httpcall返回時的每個響應

在訂閱中,您知道何時返回所有響應和值數組

const observableObj = (obj) => Observable.of(obj)

class Requests {

 private query_arr = ['test1','test2','test3']
 private url = 'https://testsoapi.apispark.net/v1/entities'

 public make() {
   this.processHttp().subscribe(
        (d) => {
          console.log(d)              
        },
        (e) => {
          console.log(e)
        },
        () => {
          console.log("http calls are done")
        })

 }

 private httpCall(options : RequestOptions) : Observable<Response> {
   let username : string = 'xxx'
   let password : string = 'yyy'
   let headers = new Headers()
   headers.append("Authorization", "Basic " + btoa(username + ":" + password))
   headers.append("Content-Type", "application/x-www-form-urlencoded")
   options.headers = headers
   return this.http.get(this.url,options)
 }

 private createRequestOptions(option1 : string) {
   let data = {'option1':option1}
   let params = new URLSearchParams()
   for(var key in data) {
     params.set(key, data[key])
   }
   let options = new RequestOptions({
     search: params
   })
   return options
 }

 private processHttp() {
    return Observable.forkJoin(
        this.query_arr.map(option => {
            return this.httpCall(createRequestOption(option)).flatMap((res: Response) => {
                return observableObj(res.json())
            })
        }))            
 }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM