Send multiple asynchronous HTTP GET requests

半城伤御伤魂 提交于 2020-01-11 09:52:53

问题


I've got an API call that I need to make multiple times as the API doesn't support requests for multiple items. What I have written so far ends up in an endless loop of sending GET requests to the server. I believe I don't understand the nature of Observables in the below example. My assumption is that each call in the while loop subscribes to a new single object and that when it is resolved it will be placed in the array. How can I modify the below code to achieve what I want?

getSingle(): Observable<Single> {
    return this.http.get(this.url, this.options)
     .map((r: Response) => r.json().data as Single);
}

getMultiple(num: number): Single[] {
    let multiple: Single[] = [];

    let i = 0;
    while (i < num) {
        this.getSingle().subscribe(single => {
            multiple.push(single);
            console.log('Success');
            i++;
        }, err => {
            console.log('Failure');
        });
   }

   return multiple;
}

回答1:


Using the while loop to make multiple asynchronous HTTP requests, and then subscribe to all of them separately should be avoided in order not to have many Observable connections opened. We can use Observable.forkJoin operator instead.

This is how the implementation should look like:

getSingle(singleUrl: string): Observable<Single> {
    return this.http.get(singleUrl, this.options)
        .map((r: Response) => r.json().data as Single);
};

getMultiple(): Observable<Array<Single>> {
    let singleUrls = ['singleUrl1', 'singleUrl2', 'singleUrl3']; // can be replaced with any 'Single' identifier

    let singleObservables = singleUrls.map((singleUrl: string, urlIndex: number) => {
        return this.getSingle(singleUrl)
            .map(single => single as Single)
            .catch((error: any) => {
                console.error('Error loading Single, singleUrl: ' + singleUrl, 'Error: ', error);
                return Observable.of(null); // In case error occurs, we need to return Observable, so the stream can continue
            });
    });

    return Observable.forkJoin(singleObservables);
};

this.getMultiple().subscribe(
    (singles: Array<Single>) => {
        console.log(singles); // [Single, Single, Single];
        // In case error occured e.g. for the 'singleUrl' (our 'Single' identifier) at position 1,
        // Output wil be: [Single, null, Single];
    }
);

Hope this helps!




回答2:


Ideally you would only subscribe once in the constructor since a subscribe block can be called many times and then use an RxJS subject and next() it inside the loop

However, a quick fix if you don't care too much is to:

this.getSingle().first().subscribe

you will need to import the first operator. This will ensure subscribe only is called once only. that way you can sub many times no worries.

I'm guessing the reason you are getting infinite HTTP request is that you failure block is being hit and you need to do ...

}, err => {
       i++;
        console.log('Failure');
 });


来源:https://stackoverflow.com/questions/41619312/send-multiple-asynchronous-http-get-requests

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!