Skip to main content
Svelte Fundamentals
CHAPTER 15 Beginner

API Calls and Fetching Data

Updated: May 18, 2026
5 min read

# CHAPTER 15

API Calls and Fetching Data

1. Chapter Introduction

Modern web applications are driven by data from REST APIs. In Svelte, you can fetch data using the standard browser fetch() API inside onMount, or elegantly handle the three async states (loading, success, error) directly in the template using {#await}. This chapter covers all patterns.

2. Learning Objectives

  • Fetch data inside onMount with loading/error state management.
  • Use {#await} for declarative async templates.
  • Handle API errors gracefully.
  • Implement data refresh and search.
  • Build a Weather Application.

3. Pattern 1: Manual State Management

svelte
1234567891011121314151617181920212223242526272829303132
<script>
  import { onMount } from &#039;svelte';

  let posts = [];
  let loading = true;
  let error = null;

  onMount(async () => {
    try {
      const res = await fetch(&#039;https://jsonplaceholder.typicode.com/posts?_limit=5');
      if (!res.ok) throw new Error(`HTTP Error: ${res.status}`);
      posts = await res.json();
    } catch (e) {
      error = e.message;
    } finally {
      loading = false;
    }
  });
</script>

{#if loading}
  <div class="spinner">Loading...</div>
{:else if error}
  <div class="error">❌ {error}</div>
{:else}
  {#each posts as post (post.id)}
    <div class="post-card">
      <h3>{post.title}</h3>
      <p>{post.body.slice(0, 100)}...</p>
    </div>
  {/each}
{/if}

4. Pattern 2: {#await} in Template

svelte
12345678910111213141516171819202122232425
<script>
  async function getPosts() {
    const res = await fetch(&#039;https://jsonplaceholder.typicode.com/posts?_limit=5');
    if (!res.ok) throw new Error(&#039;Failed to fetch');
    return res.json();
  }

  let postsPromise = getPosts();

  function refresh() {
    postsPromise = getPosts(); // Re-runs the await block!
  }
</script>

<button on:click={refresh}>🔄 Refresh</button>

{#await postsPromise}
  <p>Loading posts...</p>
{:then posts}
  {#each posts as post (post.id)}
    <h3>{post.title}</h3>
  {/each}
{:catch error}
  <p class="error">Error: {error.message}</p>
{/await}

5. Mini Project: Weather Application

svelte
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
<!-- WeatherApp.svelte -->
<script>
  const API_KEY = &#039;YOUR_API_KEY'; // openweathermap.org
  const API_URL = &#039;https://api.openweathermap.org/data/2.5';

  let city = &#039;';
  let weatherPromise = null;
  let searchInput;

  async function getWeather(cityName) {
    const res = await fetch(`${API_URL}/weather?q=${cityName}&appid=${API_KEY}&units=metric`);
    if (!res.ok) {
      if (res.status === 404) throw new Error(`City "${cityName}" not found`);
      throw new Error(&#039;Weather service unavailable');
    }
    return res.json();
  }

  function search() {
    if (city.trim()) {
      weatherPromise = getWeather(city.trim());
    }
  }

  function handleKeydown(e) {
    if (e.key === &#039;Enter') search();
  }

  const weatherIcons = {
    Clear: &#039;☀️', Clouds: '☁️', Rain: '🌧️', Snow: '❄️',
    Thunderstorm: &#039;⛈️', Drizzle: '🌦️', Mist: '🌫️'
  };
</script>

<div class="weather-app">
  <h1>🌤️ Weather App</h1>

  <div class="search-bar">
    <input
      bind:value={city}
      bind:this={searchInput}
      on:keydown={handleKeydown}
      placeholder="Enter city name..."
    />
    <button on:click={search} disabled={!city.trim()}>Search</button>
  </div>

  {#if weatherPromise}
    {#await weatherPromise}
      <div class="loading">Fetching weather...</div>
    {:then weather}
      <div class="weather-card">
        <div class="city-name">{weather.name}, {weather.sys.country}</div>
        <div class="icon">{weatherIcons[weather.weather[0].main] || &#039;🌡️'}</div>
        <div class="temp">{Math.round(weather.main.temp)}°C</div>
        <div class="desc">{weather.weather[0].description}</div>
        <div class="details">
          <span>💧 {weather.main.humidity}% humidity</span>
          <span>💨 {weather.wind.speed} m/s</span>
          <span>👁️ {(weather.visibility / 1000).toFixed(1)} km</span>
        </div>
      </div>
    {:catch error}
      <div class="error">❌ {error.message}</div>
    {/await}
  {:else}
    <p class="hint">Enter a city name to get the current weather.</p>
  {/if}
</div>

6. Common Mistakes

  • No error handling: Always wrap fetch in try/catch or use {:catch}.
  • Not checking res.ok: fetch only rejects on network errors, not HTTP 4xx/5xx. Always check if (!res.ok).

7. MCQs

Question 1

Does fetch() throw an error for HTTP 404 responses?

Question 2

What property tells you if an HTTP response was successful?

Question 3

What is the simplest Svelte pattern for async template rendering?

Question 4

How do you refresh data in {#await} pattern?

Question 5

Where is the best place to call fetch in a Svelte component?

Question 6

What HTTP header do you need for sending JSON in a POST request?

Question 7

How do you send a POST request with JSON body?

Question 8

What does finally block do in try/catch/finally for loading state?

Question 9

What do you check to get HTTP error status code?

Question 10

What free API can you use for testing without an API key?

8. Interview Questions

  • Q: What is the difference between a network error and an HTTP error? How does Svelte handle each?
  • Q: Compare the onMount state management pattern with the {#await} template pattern. When would you choose each?

9. Summary

Svelte provides two elegant patterns for async data fetching: manual state management in onMount for full control, and the {#await} block for declarative, colocated loading/success/error templates. Always check res.ok and handle errors gracefully to build robust applications.

10. Next Chapter Recommendation

In Chapter 16: Working with JSON and REST APIs, we build a complete CRUD Blog application with GET, POST, PUT, and DELETE operations against a REST API.

Finish this Chapter

Save your progress on your learning path and prepare for coding interview challenges.

Discussion

Join the discussion

Log in or create a free account to participate.

Sort: ·