27

I've been following a tutorial and came across the following code snippet:

const myAsyncFunction = async () => {
    const usersResponse = await fetch(
        'https://jsonplaceholder.typicode.com/users'
    )
    const userJson = await usersResponse.json();
    const secondUser = userJson[1];
    console.log(secondUser);
    const posts = await fetch (
        'https://jsonplaceholder.typicode.com/posts?userId=' + secondUser.id
    );
    const postsJson = await posts.json();
    console.log(postsJson);
}
myAsyncFunction();

Shouldn't the converting of a response to a JSON object happen instantly, the same way fetching a value from an array e.g. userJson[1] does? Why is it required to await usersResponse.json() and posts.json()?

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
user3545063
  • 681
  • 8
  • 17
  • 1
    Because reading and parsing the request body doesn't have to be blocking. – jonrsharpe Jan 01 '20 at 19:40
  • Ok thanks! I may have picked up a wrong impression of promises then, as I believed that async operations generally relate solely to http requests / fetches. But does that also mean that local cpu heavy operations are async by default? – user3545063 Jan 01 '20 at 19:44
  • 2
    @user3545063 No it doesn't mean that a local CPU-heavy operation would be async. That would be synchronous. `.json()` is async because the the entire response body may not have been read at the time `.json()` is called. Look at the method descriptions on [the Response MDN page](https://developer.mozilla.org/en-US/docs/Web/API/Response) and note that several of them including `.json()` say "Takes a Response stream and _reads it to completion_." (emphasis added) – Michael Geary Jan 01 '20 at 19:46

1 Answers1

65

After the initial fetch() call, only the headers have been read. So, to parse the body as JSON, first the body data has to be read from the incoming stream. And, since reading from the TCP stream is asynchronous, the .json() operation ends up asynchronous.

Note: the actual parsing of the JSON itself is not asynchronous. It's just the retrieving of the data from the incoming stream that is asynchronous.

jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • 1
    Thanks @jfriend00 for the explanation. I have a question, does .json() parse the body data as it comes or it waits for the whole data to come and then parse it ? – Vaibhav Jun 06 '21 at 11:21
  • 2
    @Vaibhav - The whole body is read into memory and then it is parsed. The best way to answer these questions it to just look at [the source](https://github.com/expressjs/body-parser/blob/master/lib/types/json.js#L89). – jfriend00 Jun 06 '21 at 16:18