在angular应用程序中,我有一个包含url属性的文字对象数组。 我需要对每个对象都发出一个http请求,但是要一个接一个。
示例:
let arr = [{url: 'http://example.com/url1'},{url: 'http://example.com/url2'},{url: 'http://example.com/url3'}]
(这是一个示例,它们可能是更多的对象,但我不知道有多少个对象)
现在,我想向第一个URL发出请求,当我们收到响应时(或无所谓,则无所谓),然后我向第二个URL发出请求。如何有效地实现该请求?
我不想一次发出这些请求-每个请求都只能在上一次成功或失败之后进行。
答案 0 :(得分:1)
使用rxJs中的 concatAll()方法,该方法收集可观察对象并在上一个完成时订阅下一个。 (或者您可以一次使用 forkJoin 进行多个请求。)
forkJoin -这将对您的所有请求进行分组并一个接一个地执行。 forkJoin 等待每个http请求完成,并将每个http调用返回的所有可观察对象分组为单个可观察数组,最后返回该可观察数组。
它接受数组作为参数。例如-
let response1 = this.http.get(requestUrl1);
let response2 = this.http.get(requestUrl2);
let response3 = this.http.get(requestUrl3);
return Observable.forkJoin([response1, response2, response3]);
当您有一组可观察对象并且仅在乎每个对象的最终发射值时,最好使用此运算符。
通过另一种方式,您可以在上一个请求的错误或成功块中调用每个请求,这是一个漫长的过程。
答案 1 :(得分:0)
用户forkJoin
Fork Join
let arr = [{url: 'http://example.com/url1'},{url: 'http://example.com/url2'},{url:
'http://example.com/url3'}]
forkJoin(arr);
答案 2 :(得分:0)
您可以将观测值与flatMap
结合使用。由于您具有一个可观察变量列表(或要转换为可观察变量的URL列表),因此可以使用reduce
。
示例:
// just some options to make a simple GET without parsing JSON
// and reading the response status
const httpOptions = {
headers: new HttpHeaders({
'Accept': 'text/html, application/xhtml+xml, */*',
'Content-Type': 'application/x-www-form-urlencoded'
}),
responseType: 'text',
observe: 'response'
};
const urls = [
{ url: 'www.google.com' },
{ url: 'www.stackoverflow.com' },
{ url: 'www.imgur.com' },
{ url: 'www.reddit.com' },
];
const reducer = (cur, acc) => acc.pipe(
flatMap(r => cur)
);
const all$ = urls.map(({url}) =>
// create the get requests
http.get(url, httpOptions).pipe(
// do something with the result
tap(r => console.log(r.url + ': ' + r.status))
))
.reverse()
.reduce(reducer);
all$.subscribe(x => {});
答案 3 :(得分:0)
可能的解决方案是使用 concatMap , toArray 和 switchMapTo 。
所以首先您有一个URL列表:
let arr = [{url: 'http://example.com/url1'},{url: 'http://example.com/url2'}]
然后将它们转换为可观察的:
of(arr)
.pipe(
concatMap(r=> http.get(r.url)), //MAKE EACH REQUEST AND WAIT FOR COMPLETION
toArray(), // COMBINE THEM TO ONE ARRAY
switchMapTo(http.get("FINALURL") // MAKE REQUEST AFTER EVERY THING IS FINISHED
)).subscribe()
答案 4 :(得分:0)
使用 concatMap
,确保使用 catchError
,因为如果一个链接产生错误,您不希望整个链都失败。
let results$ = from(arr).pipe(
concatMap(({ url }) =>
requestData(url).pipe(catchError(err => of(`error from ${url}`)))
)
);
答案 5 :(得分:-1)
为此,我们可以使用棘手的方法。您必须在如下所示的服务中创建方法。
// TestService.ts
callUrlAsync(url): any[] {
return this._http.get<any>(url);
}
在组件中,您必须按以下方式调用此方法。
//component.ts
let arr = [{url: 'http://example.com/url1'},{url: 'http://example.com/url2'},
{url:'http://example.com/url3'}]
public i = 0;
//trigger method
testMethod(){
this.callUrl(this.arr[0]);
}
callUrl(url){
this.testService.callUrlAsync(url)
.subscribe(data => {
console.log(data);
if(this.arr.length > this.i){
this.i++;
this.callUrl(this.arr[this.i]);
}
}
}, error => {
this.Error(error);
if(this.arr.length > this.i){
this.i++;
this.callUrl(this.arr[this.i]);
}
}
);
}