Why does JavaScript's fetch make me wait TWICE?

00:06:23
https://www.youtube.com/watch?v=Ki64Cnyf_cA

Summary

TLDRThis video explains the underlying reason why JavaScript's fetch method requires two await calls: one to wait for the response headers, and another for the response.json() to acquire the body content. The fetch method captures the headers as soon as they are received, allowing it to resolve early. However, the response.json() method must be awaited because it returns a promise; the body could take significant time to fully arrive, especially if a large amount of data is being transferred. An explanation of the process is demonstrated with a Node.js server that sends data slowly over the network to show the waiting process in real-time. The presenter also demonstrates how to access the response body more quickly at the byte level with JavaScript's text decoder, allowing for streaming data processing as it arrives, exemplifying a more efficient way of handling asynchronous data.

Takeaways

  • 🕒 JavaScript fetch involves two awaits: first for headers, then for the body.
  • 📜 response.json() method returns a promise; hence, it requires awaiting.
  • 🔄 JSON.parse is synchronous, unlike response.json which is asynchronous.
  • 🌐 Fetch resolves after receiving response headers before the body.
  • ⏳ Response body arrival time can vary with network conditions and size.
  • 📡 Different approach: stream data with TextDecoder for real-time processing.
  • 📥 Data streamed byte by byte can be appended to the DOM immediately.
  • 🔧 Demonstration includes a simple Node.js server sending data slowly to illustrate the process.
  • 🌈 Example video features a custom web app with a gradient for visual demonstration.
  • 💻 The explanation includes a practical coding illustration on how await functions in fetch.

Timeline

  • 00:00:00 - 00:06:23

    The speaker is discussing the use of 'fetch' in JavaScript and why it requires two 'await' statements. They explain that when you call 'fetch', you initially await the response. After that, you must await the JSON parsing, as 'response.json()' returns a promise. The speaker questions why this is the case, given that 'json.parse()' is synchronous. They explore this by looking at how HTTP messages work, where a response first returns headers and then the body, which may take longer to arrive. They illustrate this using a simple Node.js app that sends data one byte at a time, demonstrating the difference in timing between receiving headers and the body. Lastly, they show how to handle data as it comes in using a text decoder and a for-await loop in the browser.

Mind Map

Video Q&A

  • Why do you need to await twice with JavaScript fetch?

    You need to await the fetch call to get the response headers, and then await again for response.json() to resolve, which retrieves the full response body.

  • What does response.json() return?

    response.json() returns a promise, which is why it requires awaiting.

  • Why does JSON.parse not need an await?

    JSON.parse is synchronous and doesn't require await, unlike response.json() which is asynchronous.

  • What allows fetch to resolve before the response body is available?

    Fetch resolves initially after receiving the response headers from the server, while the body can be processed asynchronously.

  • Why might a response body take a long time to be available?

    The response body can take longer due to network latency or large data size being transferred.

View more video summaries

Get instant access to free YouTube video summaries powered by AI!
Subtitles
en
Auto Scroll:
  • 00:00:00
    hey what's going on so a little while
  • 00:00:02
    ago I watched a video where somebody was
  • 00:00:04
    explaining why when you use fetch in
  • 00:00:07
    JavaScript you need these two awaits so
  • 00:00:10
    you call fetch on some endpoint you
  • 00:00:12
    await a response okay you've got a
  • 00:00:14
    response now if I want to call Jason I
  • 00:00:18
    also have to await now their explanation
  • 00:00:20
    which is correct was that response.
  • 00:00:23
    Jason returns a promise yeah okay so
  • 00:00:25
    that's right but the question is why
  • 00:00:27
    does response. Jason return a promise
  • 00:00:30
    right and maybe you already know maybe
  • 00:00:31
    that's obvious but if you think about it
  • 00:00:33
    for a second so
  • 00:00:35
    json.parse you've probably called this
  • 00:00:37
    function before in JavaScript this is a
  • 00:00:39
    synchronous uh method right on the or
  • 00:00:43
    static function whatever it is on Jason
  • 00:00:46
    it's synchronous right I don't have to
  • 00:00:48
    await it but this one I do have to await
  • 00:00:50
    so what's going on so in this video I'm
  • 00:00:52
    going to show you what exactly is going
  • 00:00:53
    on you could probably
  • 00:00:55
    guess so of course we're going to go to
  • 00:00:57
    mdn and take a look and so what it exps
  • 00:01:00
    here is that the fetch method takes one
  • 00:01:02
    mandatory argument so that was the uh
  • 00:01:04
    endpoint that we're calling right or the
  • 00:01:06
    URL URI whatever and then it returns a
  • 00:01:09
    promise that resolves to the response
  • 00:01:12
    okay but you get that as soon as the
  • 00:01:14
    server responds with headers okay so
  • 00:01:17
    let's let's take a look quick at what an
  • 00:01:19
    HTTP message looks like so normally HTTP
  • 00:01:21
    messages are sort of divided into you
  • 00:01:24
    have headers and then you have a body
  • 00:01:25
    right you have like this blank line in
  • 00:01:27
    between so what it's saying is that your
  • 00:01:31
    initial fetch is going to resolve as
  • 00:01:33
    soon as you get these headers back okay
  • 00:01:35
    great so you get these headers now how
  • 00:01:37
    many headers are you going to have
  • 00:01:38
    normally not a lot you could have a very
  • 00:01:40
    very big number I believe that there's
  • 00:01:42
    actually ways of attacking servers but
  • 00:01:44
    just by flooding them with headers but
  • 00:01:45
    anyway there's not going to be too many
  • 00:01:47
    headers right probably and then the body
  • 00:01:49
    is probably going to be a lot longer
  • 00:01:52
    right and so then it says once the
  • 00:01:54
    response is received so the response you
  • 00:01:55
    get as soon as you get the headers once
  • 00:01:57
    the response is received or retrieved
  • 00:02:00
    then there's number of methods you can
  • 00:02:01
    call like Jason that uh will get you the
  • 00:02:03
    body content so that's exactly what's
  • 00:02:05
    happening right so if I uh go back over
  • 00:02:09
    to my code here with this line right
  • 00:02:11
    here I'm getting the headers and then
  • 00:02:13
    with this line right here I'm getting
  • 00:02:15
    the body and so the reason I have to
  • 00:02:18
    wait is because that body could take a
  • 00:02:19
    very long time to Crum across the wire I
  • 00:02:21
    want to show you what that would look
  • 00:02:22
    like so what I have here is a very very
  • 00:02:25
    simple node application no framework
  • 00:02:27
    nothing right and I'm using HTTP to
  • 00:02:30
    create a server and then I'm listening
  • 00:02:33
    and so if I get a get request to slash
  • 00:02:35
    right then I return some HTML we'll look
  • 00:02:37
    at that in a second but otherwise I
  • 00:02:39
    return Jason on the Jason endpoint but I
  • 00:02:43
    do something interesting I think
  • 00:02:45
    interesting is I read the file and I
  • 00:02:48
    send it back over one bite at a time one
  • 00:02:51
    character at a time in this case it's
  • 00:02:53
    one bite at a time uh because it doesn't
  • 00:02:55
    matter because it's all asky okay so
  • 00:02:58
    what happens is when the client hits
  • 00:02:59
    this point right away they're going to
  • 00:03:00
    get the headers right so the first
  • 00:03:03
    promise is going to resolve right fetch
  • 00:03:04
    is going to resolve but then I read from
  • 00:03:06
    a file and I slowly every two
  • 00:03:09
    milliseconds send them one character
  • 00:03:11
    right now 2 milliseconds seems pretty
  • 00:03:12
    quick but when you have a lot of
  • 00:03:13
    characters and I do in this uh terrible
  • 00:03:16
    chat GPT story that I generated uh when
  • 00:03:20
    you send this whole thing over uh it
  • 00:03:22
    takes actually quite a while so here we
  • 00:03:24
    are with this web application kind of
  • 00:03:26
    fun thing here um this code is actually
  • 00:03:28
    the code right from my indexi HTML file
  • 00:03:31
    so I'm taking the function I'm
  • 00:03:34
    stringifying it and then just throwing
  • 00:03:35
    it into this div so if I actually change
  • 00:03:37
    the HTML this changes I think it's kind
  • 00:03:39
    of cool anyway doesn't really matter so
  • 00:03:42
    look at this code right here and I'm
  • 00:03:44
    making a request I'm awaiting the Json
  • 00:03:48
    I'm getting the headers right and then
  • 00:03:50
    I'm getting the object but this is look
  • 00:03:52
    I'm response. Jason I'm awaiting that
  • 00:03:54
    and we know it's going to take a long
  • 00:03:55
    time and then I'm console logging turn
  • 00:03:57
    Jason into an object I'm console logging
  • 00:03:59
    the object so uh let's click this right
  • 00:04:03
    here okay you saw making request
  • 00:04:05
    happened right away got response headers
  • 00:04:07
    right away because nobody has to wait
  • 00:04:09
    for that and then finally the story came
  • 00:04:11
    across right let's let's look at this
  • 00:04:13
    one more time but from the network
  • 00:04:14
    perspective so I'm going to click this
  • 00:04:15
    here okay fetch Jason Jason came back
  • 00:04:19
    right away we already know it's a 200
  • 00:04:21
    right so like somebody asked you was
  • 00:04:23
    that 200 response yeah we know right
  • 00:04:24
    away it was a 200 response because the
  • 00:04:25
    server sends over the headers first
  • 00:04:27
    right let let's watch that again so I'm
  • 00:04:29
    going to clear this
  • 00:04:31
    out okay fetch
  • 00:04:33
    Jason okay and then you can see it
  • 00:04:36
    streaming in right bite by bite and
  • 00:04:39
    there's a lot of lot of bites here right
  • 00:04:41
    and and they're streaming in right and
  • 00:04:42
    then like yeah here here's the whole
  • 00:04:44
    thing and uh if actually what I can do
  • 00:04:46
    here is I can kind of let let's throw me
  • 00:04:50
    out of the way here I can kind of watch
  • 00:04:52
    it so I can go over here and then I can
  • 00:04:55
    see it kind of like this is not designed
  • 00:04:58
    to do this but there's the response
  • 00:05:00
    slowly coming in right Chrome is not
  • 00:05:02
    having a good time with this but hey it
  • 00:05:04
    kind of It kind of works okay so that's
  • 00:05:06
    fine but what if you actually want to
  • 00:05:08
    get the response body as it comes in
  • 00:05:10
    right so you can't wait for the whole
  • 00:05:13
    thing to be done because maybe it it'll
  • 00:05:14
    never be done right maybe you're just
  • 00:05:16
    dipping into a stream you're getting the
  • 00:05:17
    stuff and then you're you're leaving
  • 00:05:19
    right so um a wait Jason sure I get my
  • 00:05:23
    headers back and then I can make a text
  • 00:05:25
    decoder right this is just in the
  • 00:05:26
    browser the browser lets you do this and
  • 00:05:28
    then I can do a four A8 right of
  • 00:05:32
    response body which is pretty cool and
  • 00:05:35
    then I'm going to decode the value and
  • 00:05:37
    then I'm going to take that and append
  • 00:05:40
    it so basically I'm reading it bite by
  • 00:05:43
    bite and I'm throwing it into the Dom so
  • 00:05:46
    this is same thing you you see the same
  • 00:05:47
    thing in the network tab right but here
  • 00:05:49
    you're going to see the results as they
  • 00:05:51
    come
  • 00:05:54
    in I actually made this website a little
  • 00:05:56
    while ago I didn't have time to make a
  • 00:05:58
    video I'm very impressed by the gradient
  • 00:05:59
    very very proud of myself for having
  • 00:06:01
    that but it's the same idea except now
  • 00:06:03
    you can see it as it comes in if you
  • 00:06:05
    want to support the important work that
  • 00:06:06
    I do here um you know I'm constantly
  • 00:06:09
    being attacked by uh whatever these
  • 00:06:11
    things are and uh you know if you could
  • 00:06:13
    maybe take one or two of them out or
  • 00:06:15
    distract them or or something that that
  • 00:06:18
    would uh that would go a long way to
  • 00:06:20
    improving the quality of the
Tags
  • JavaScript
  • fetch
  • await
  • asynchronous
  • promise
  • response.json
  • networking
  • Node.js
  • streaming
  • HTTP