Skip to Content
Course content

211: Working with the Fetch API and Streaming Responses

Click on the "Edit" button in the top corner of the screen to edit your slide content.

I see this happen all the time during code reviews: a developer calls await fetch(url) and immediately assumes that because the promise resolved, the data is sitting there waiting for them. They treat the Response object like a completed package delivered to their door.

The Myth: "The Promise Resolves When the Data Arrives"

It's a subtle but critical misunderstanding. Let's look at why this is wrong. If you're fetching a 500MB JSON file, the fetch() promise doesn't wait for all 500 million bytes to travel across the ocean from the server to your browser. If it did, your app would feel frozen, and you'd have no way to show a progress bar.

// The common mistake: thinking the data is "done" here
const response = await fetch('https://api.example.com/massive-dataset');
console.log('Data is here!'); // WRONG. Only the headers are here.

At the moment that first await resolves, the browser has only received the HTTP headers. It knows the status code (200, 404, etc.) and the content type, but the actual body of the response is still streaming in over the network. If you try to use the response before consuming the body, you're essentially standing at the front door while the delivery driver is still unloading the truck.

The Reality: The Response is a Stream

To actually get the data, you usually call response.json() or response.text(). These methods are also asynchronous because they have to wait for the rest of the stream to finish. But here is the pro tip: you don't have to wait for the whole thing. You can hook directly into the response.body, which is a ReadableStream.

This is how modern AI chat interfaces work. When you see ChatGPT "typing" its response word-by-word, it isn't waiting for the entire paragraph to be generated. It's reading the response stream chunk by chunk as the server pushes them out.

Reading the Stream Manually

If you want to process data as it arrives—perhaps to update a progress bar or render text in real-time—you need to get a reader from the stream. I'll show you how to do this using a while loop. It looks a bit more verbose than .json(), but it gives you total control.

async function streamData(url) {
  const response = await fetch(url);
  const reader = response.body.getReader();
  const decoder = new TextDecoder(); // Converts bytes to string
  
  let done = false;
  while (!done) {
    const { value, done: doneReading } = await reader.read();
    done = doneReading;
    
    if (value) {
      // 'value' is a Uint8Array containing a chunk of the response
      const chunk = decoder.decode(value, { stream: true });
      console.log('Received chunk:', chunk);
      // Here is where you'd update your UI in real-time
    }
  }
  console.log('Stream complete.');
}

A quick side note: TextDecoder is essential here. The stream gives you Uint8Array (raw bytes). If you just try to print those, you'll see a bunch of numbers. The decoder turns those bytes back into human-readable text. I've spent way too many hours debugging "weird numbers" in my console only to realize I forgot to decode the stream.

Using this pattern, you can handle massive files without crashing the browser's memory, because you're only holding one small "chunk" of the data at a time rather than the entire 500MB blob.




📋 Practical Task

Build a Real-Time Log Streamer

You are building a developer dashboard that monitors a server's logs. Instead of waiting for a massive log file to download completely, you need to display the logs line-by-line as they arrive from the server.

Requirements:

  • Create a function streamLogs(url, displayElement).
  • Use the fetch API to connect to the provided URL.
  • Access the response.body and use a ReadableStreamDefaultReader to read the data.
  • Use TextDecoder to convert the chunks into strings.
  • Append each received chunk to the displayElement (an HTML <div>) immediately, without overwriting the previous content.
  • Log "Log Stream Finished" to the console once the stream is fully consumed.

Hint: Use a mock streaming URL or a local server that sends data slowly to verify that your UI updates incrementally rather than all at once.

Rating
0 0

There are no comments for now.

to be the first to leave a comment.