Angular Async HTTP requests not being send asynchronously
Asked Answered
J

2

8

Essentially my problem is - I have 6 different endpoints that return different numbers - I want to be able to send 6 requests asynchronously but using the chrome tools I see that they run sequentially not asynchronously.

  ngOnInit() {
    private readonly TEMP_URL: string = 'https://www.random.org/integers/?num=1&min=1&max=100000&col=1&base=10&format=plain&rnd=new';
    const result1 = this.http.get<Number>(this.TEMP_URL);
    const result2 = this.http.get<Number>(this.TEMP_URL);
    const result3 = this.http.get<Number>(this.TEMP_URL);
    const result4 = this.http.get<Number>(this.TEMP_URL);
    const result5 = this.http.get<Number>(this.TEMP_URL);
    const result6 = this.http.get<Number>(this.TEMP_URL);
    const result7 = this.http.get<Number>(this.TEMP_URL);


    forkJoin(result1,result2,result3,result4,result5,result6,result7).subscribe(results  => {
                    this.retVal0= results[0];
                    this.retVal1 = results[1];
                    this.retVal2 = results[2];
                    this.retVal3= results[3];
                    this.retVal4= results[4];
                    this.retVal5= results[5];
                    this.retVal6= results[6];
                    this.retVal7= results[7];
            });
  };

enter image description here

Jdavie answered 6/8, 2019 at 14:3 Comment(7)
What happens if you add the async keyword to ngOnInit()?Sigismundo
@Sigismundo the same resultJdavie
@Liam these are the only HTTP requests being sent during the life-time of the appJdavie
@Liam updated the image to reflect all events on page loadJdavie
What if you try using mergeMap() instead? stackblitz.com/edit/angular-mrr4efSimard
I tried it without forkJoin, basically calling .subscribe on every result1 - result8 line by line. The result was the same, it is not executed asynchronously. I even tried logging the result of result1 in result2 callback and it was there.Operose
@Operose yeah, its doing my head in. seems like it should be such an easy thing to do.Jdavie
O
3

Your code is fine, the problem comes directly from Chrome. By inspecting the requests you can see that they are stalled / queued. If you do the same inspection in another browser (Firefox), you will see that the requests are made in asynchronous way without being queued.

Queued or Stalled Requests

Too many requests are being made on a single domain. On HTTP/1.0 or HTTP/1.1 connections, Chrome allows a maximum of six simultaneous TCP connections per host.

Bear in mind that being behind the proxy will lower the number of maximum simultaneous requests - this means that you will probably get stalled requests even with two requests.

The bad thing is that you won't be able to fix this by editing your Angular code. The possible fixes only include network setting modifications:

  • Implement domain sharding if you must use HTTP/1.0 or HTTP/1.1
  • Use HTTP/2. Don't use domain sharding with HTTP/2.
  • Remove or defer unnecessary requests so that critical requests can download earlier
Operose answered 6/8, 2019 at 15:17 Comment(1)
Thank you Dino - Just tried on Firefox and IE, confirms what you said.Jdavie
D
4

In your example you're requesting the same resource multiple times.

Chrome caches the response and uses a cache locking mechanism that checks the cache before sending the next request for the same resource.

The cache implements a single writer - multiple reader lock so that only one network request for the same resource is in flight at any given time.

Note that the existence of the cache lock means that no bandwidth is wasted re-fetching the same resource simultaneously. On the other hand, it forces requests to wait until a previous request finishes downloading a resource (the Writer) before they can start reading from it, which is particularly troublesome for long lived requests. Simply bypassing the cache for subsequent requests is not a viable solution as it will introduce consistency problems when a renderer experiences the effect of going back in time, as in receiving a version of the resource that is older than a version that it already received (but which skipped the browser cache).

https://www.chromium.org/developers/design-documents/network-stack/http-cache

You should see the requests being send simultaneously if you disable the cache in the developer tools.

You could also add some unique number to the query string of every url:

this.TEMP_URL + '?unique=<yourUniqueNumber>'
Demirelief answered 6/8, 2019 at 15:27 Comment(0)
O
3

Your code is fine, the problem comes directly from Chrome. By inspecting the requests you can see that they are stalled / queued. If you do the same inspection in another browser (Firefox), you will see that the requests are made in asynchronous way without being queued.

Queued or Stalled Requests

Too many requests are being made on a single domain. On HTTP/1.0 or HTTP/1.1 connections, Chrome allows a maximum of six simultaneous TCP connections per host.

Bear in mind that being behind the proxy will lower the number of maximum simultaneous requests - this means that you will probably get stalled requests even with two requests.

The bad thing is that you won't be able to fix this by editing your Angular code. The possible fixes only include network setting modifications:

  • Implement domain sharding if you must use HTTP/1.0 or HTTP/1.1
  • Use HTTP/2. Don't use domain sharding with HTTP/2.
  • Remove or defer unnecessary requests so that critical requests can download earlier
Operose answered 6/8, 2019 at 15:17 Comment(1)
Thank you Dino - Just tried on Firefox and IE, confirms what you said.Jdavie

© 2022 - 2024 — McMap. All rights reserved.