[英]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.