admin管理员组文章数量:1433902
In angular app I have an array of literal objects containing a url property. I need to make a http request for each of these object, but one after another.
example:
let arr = [
{url: ''},
{url: ''},
{url: ''}
]
(that is an example, they may be more of objects, and I don't know how many)
Now, I want to make a request to first url and when we have a response from it (or error, doesn't matter) THEN I want to make a request to second etc. Any idea how to efficiently implement that?
I don't want to make these request at single time - each one should be made only after previous was successful or failure.
In angular app I have an array of literal objects containing a url property. I need to make a http request for each of these object, but one after another.
example:
let arr = [
{url: 'http://example./url1'},
{url: 'http://example./url2'},
{url: 'http://example./url3'}
]
(that is an example, they may be more of objects, and I don't know how many)
Now, I want to make a request to first url and when we have a response from it (or error, doesn't matter) THEN I want to make a request to second etc. Any idea how to efficiently implement that?
I don't want to make these request at single time - each one should be made only after previous was successful or failure.
Share Improve this question edited Jul 25, 2021 at 6:46 Aviad P. 32.7k15 gold badges111 silver badges126 bronze badges asked Dec 12, 2018 at 7:27 deasedease 3,07613 gold badges42 silver badges77 bronze badges6 Answers
Reset to default 1A possible solution would be to use concatMap, toArray and switchMapTo.
So first you have a list of urls:
let arr = [{url: 'http://example./url1'},{url: 'http://example./url2'}]
Then you transform them to an Observable:
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()
We can use tricky method for this. You have to create method in the service like below.
// TestService.ts
callUrlAsync(url): any[] {
return this._http.get<any>(url);
}
In the ponent you have to call this method as follows.
//ponent.ts
let arr = [{url: 'http://example./url1'},{url: 'http://example./url2'},
{url:'http://example./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]);
}
}
);
}
You can bine your observables with flatMap
. Since you have a list of observables (or a list of urls that you want to transform into observables), you can do this with reduce
.
Example:
// 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.' },
{ url: 'www.stackoverflow.' },
{ url: 'www.imgur.' },
{ url: 'www.reddit.' },
];
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 => {});
User forkJoin
Fork Join
let arr = [{url: 'http://example./url1'},{url: 'http://example./url2'},{url:
'http://example./url3'}]
forkJoin(arr);
Use concatAll() method from rxJs which collect observables and subscribe to next when previous pletes. (Or you can use forkJoin for multiple request at single time.)
forkJoin - This will group all your request and execute one by one. forkJoin waits for each http request to plete and group’s all the observables returned by each http call into a single observable array and finally return that observable array.
It accepts array as parameter. for example -
let response1 = this.http.get(requestUrl1);
let response2 = this.http.get(requestUrl2);
let response3 = this.http.get(requestUrl3);
return Observable.forkJoin([response1, response2, response3]);
For ref. - https://medium./@swarnakishore/performing-multiple-http-requests-in-angular-4-5-with-forkjoin-74f3ac166d61
This operator is best used when you have a group of observables and only care about the final emitted value of each.
In another way you can call each request in previous request's error or success block, which is lengthy process.
Use concatMap
, make sure to catchError
because you don't want the entire chain to fail if one link produced an error.
StackBlitz
let results$ = from(arr).pipe(
concatMap(({ url }) =>
requestData(url).pipe(catchError(err => of(`error from ${url}`)))
)
);
本文标签:
版权声明:本文标题:javascript - Angular make multiple http request but wait for each one to finish before making a new one - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1745620538a2666655.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论