Bird
Raised Fist0
Svelteframework~8 mins

Streaming with promises in Svelte - Performance & Optimization

Choose your learning style10 modes available
Performance: Streaming with promises
MEDIUM IMPACT
This affects how quickly content appears on screen by allowing partial data to render as it arrives, improving perceived load speed.
Loading data and rendering UI progressively
Svelte
let stream = fetch('/api/data').then(res => {
  const reader = res.body.getReader();
  return new ReadableStream({
    start(controller) {
      function push() {
        reader.read().then(({done, value}) => {
          if (done) {
            controller.close();
            return;
          }
          controller.enqueue(value);
          push();
        });
      }
      push();
    }
  });
});

// In Svelte, read the stream and update reactive state (e.g., array store) as chunks arrive to render progressively
Renders UI progressively as data chunks arrive, reducing time to first meaningful paint and improving user experience.
📈 Performance GainReduces LCP by up to 50% by enabling incremental rendering and avoiding blocking on full data load.
Loading data and rendering UI progressively
Svelte
let data;
fetch('/api/data').then(res => res.json()).then(json => {
  data = json;
  // render UI only after all data is fetched
});
UI waits for the entire data fetch to complete before rendering, causing longer wait times and blocking first paint.
📉 Performance CostBlocks rendering until full data arrives, increasing LCP by 500-1000ms depending on data size.
Performance Comparison
PatternDOM OperationsReflowsPaint CostVerdict
Full data fetch before renderSingle batch DOM update1 reflow after data loadSingle paint after full data[X] Bad
Streaming data with promisesIncremental DOM updatesMultiple small reflowsMultiple smaller paints[OK] Good
Rendering Pipeline
Streaming with promises feeds data chunks to the browser incrementally, allowing the rendering engine to paint partial content early. This reduces blocking in the critical rendering path.
→Critical Rendering Path
→Layout
→Paint
⚠️ BottleneckWaiting for full data before rendering delays Layout and Paint stages.
Core Web Vital Affected
LCP
This affects how quickly content appears on screen by allowing partial data to render as it arrives, improving perceived load speed.
Optimization Tips
1Render UI progressively by streaming data instead of waiting for full fetch.
2Avoid blocking the critical rendering path with large synchronous data loads.
3Use streaming APIs to reduce Largest Contentful Paint and improve perceived speed.
Performance Quiz - 3 Questions
Test your performance knowledge
How does streaming data with promises affect Largest Contentful Paint (LCP)?
AIt worsens LCP by adding extra network overhead.
BIt improves LCP by allowing partial content to render early.
CIt has no effect on LCP.
DIt delays LCP because of multiple reflows.
DevTools: Performance
How to check: Record a performance profile while loading the page. Look for long tasks blocking rendering and when the first contentful paint occurs.
What to look for: Check if content appears progressively or only after a long delay. Early paint markers and shorter blocking times indicate good streaming performance.

Practice

(1/5)
1. What is the main benefit of using streaming with promises in Svelte when fetching data?
easy
A. It allows showing data bit by bit for faster user feedback.
B. It delays showing any data until the entire response is received.
C. It automatically caches all data without extra code.
D. It prevents any UI updates until the promise fully resolves.

Solution

  1. Step 1: Understand streaming with promises

    Streaming lets you process data as it arrives, not waiting for all data.
  2. Step 2: Connect streaming to user experience

    Showing data bit by bit gives faster feedback, improving user experience.
  3. Final Answer:

    It allows showing data bit by bit for faster user feedback. -> Option A
  4. Quick Check:

    Streaming = faster feedback [OK]
Hint: Streaming means showing data as it arrives, not waiting [OK]
Common Mistakes:
  • Thinking streaming waits for full data
  • Confusing streaming with caching
  • Believing UI updates only after full promise resolves
2. Which of the following is the correct way to start reading chunks from a fetch response stream in Svelte?
easy
A. const reader = response.getReader();
B. const reader = response.body.getReader();
C. const reader = response.readableStream();
D. const reader = response.streamReader();

Solution

  1. Step 1: Identify how to access the stream reader

    The fetch response has a body property which is a ReadableStream.
  2. Step 2: Use the correct method to get the reader

    Calling getReader() on response.body returns the reader.
  3. Final Answer:

    const reader = response.body.getReader(); -> Option B
  4. Quick Check:

    Use response.body.getReader() [OK]
Hint: Remember: reader comes from response.body.getReader() [OK]
Common Mistakes:
  • Calling getReader() directly on response
  • Using non-existent methods like readableStream()
  • Confusing response.body with response itself
3. Given this Svelte code snippet, what will be logged to the console?
async function fetchData() {
  const response = await fetch('/data');
  const reader = response.body.getReader();
  const { value, done } = await reader.read();
  console.log(new TextDecoder().decode(value));
}
fetchData();
medium
A. The first chunk of data from the response decoded as text.
B. The entire response body as a string.
C. An error because reader.read() returns a promise without value.
D. Undefined because value is not set.

Solution

  1. Step 1: Understand reader.read() output

    reader.read() returns a promise resolving to an object with value (chunk) and done (boolean).
  2. Step 2: Decode the first chunk

    The code decodes the first chunk's bytes to text and logs it.
  3. Final Answer:

    The first chunk of data from the response decoded as text. -> Option A
  4. Quick Check:

    reader.read() gives first chunk [OK]
Hint: reader.read() returns first chunk and done flag [OK]
Common Mistakes:
  • Assuming reader.read() returns full response
  • Expecting reader.read() to return undefined value
  • Confusing promise with direct value
4. What is wrong with this Svelte code that tries to stream data from fetch?
async function load() {
  const response = await fetch('/api');
  const reader = response.getReader();
  while(true) {
    const { value, done } = await reader.read();
    if(done) break;
    console.log(value);
  }
}
medium
A. Using while(true) causes infinite loop.
B. Missing await before fetch call.
C. Calling getReader() directly on response instead of response.body.
D. Not decoding value before logging.

Solution

  1. Step 1: Check how getReader() is called

    getReader() must be called on response.body, not on response itself.
  2. Step 2: Identify the error cause

    Calling response.getReader() will cause a runtime error because response has no such method.
  3. Final Answer:

    Calling getReader() directly on response instead of response.body. -> Option C
  4. Quick Check:

    Use response.body.getReader() [OK]
Hint: getReader() is on response.body, not response [OK]
Common Mistakes:
  • Calling getReader() on response
  • Forgetting to decode chunks
  • Thinking while(true) always causes infinite loop
5. You want to display a loading message that updates with each chunk of streamed data in Svelte. Which approach correctly updates the UI as chunks arrive?
hard
A. Update a local variable inside the async function without reactive binding.
B. Wait for all chunks, then update the UI once with the full data.
C. Use setTimeout to delay UI updates until streaming finishes.
D. Use a writable store to append each decoded chunk and bind it to the UI.

Solution

  1. Step 1: Understand UI reactivity in Svelte

    Svelte updates the UI when reactive variables or stores change.
  2. Step 2: Choose a method to update UI per chunk

    Using a writable store to append each chunk triggers UI updates as data arrives.
  3. Step 3: Why other options fail

    Waiting for all chunks delays UI update; setTimeout delays unnecessarily; local variable changes without binding won't update UI.
  4. Final Answer:

    Use a writable store to append each decoded chunk and bind it to the UI. -> Option D
  5. Quick Check:

    Writable store + binding = live UI updates [OK]
Hint: Use writable store to update UI reactively per chunk [OK]
Common Mistakes:
  • Updating local variables without reactive binding
  • Waiting for full data before UI update
  • Using timers instead of reactive stores
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard