Handling Promises with {#await}

+15 Mana ✨

Modern apps often fetch data from APIs. Svelte's {#await} block lets you handle loading, success, and error states directly in your template.

Basic Await Block

svelte
<script>
  async function fetchUser() {
    const res = await fetch('/api/user');
    return res.json();
  }

  let userPromise = fetchUser();
</script>

{#await userPromise}
  <p>Loading user...</p>
{:then user}
  <p>Hello, {user.name}!</p>
{:catch error}
  <p>Error: {error.message}</p>
{/await}

The Three States

StateBlockWhen it shows
Pending{#await promise}While waiting
Resolved{:then value}On success
Rejected{:catch error}On failure

Skip the Loading State

If you don't need a loading indicator:

svelte
{#await userPromise then user}
  <p>Hello, {user.name}!</p>
{/await}

Nothing shows while loading; content appears once resolved.

Real Example: Fetching Posts

svelte
<script>
  let postsPromise = fetch('/api/posts')
    .then(r => r.json());
</script>

<h1>Blog Posts</h1>

{#await postsPromise}
  <div class="skeleton-list">
    <div class="skeleton-item"></div>
    <div class="skeleton-item"></div>
    <div class="skeleton-item"></div>
  </div>
{:then posts}
  {#each posts as post}
    <article>
      <h2>{post.title}</h2>
      <p>{post.excerpt}</p>
    </article>
  {/each}
{:catch error}
  <div class="error">
    <p>Failed to load posts.</p>
    <button onclick={() => postsPromise = fetch('/api/posts').then(r => r.json())}>
      Try Again
    </button>
  </div>
{/await}

Refreshing Data

To refetch, assign a new promise:

svelte
<script>
  let dataPromise = $state(fetchData());
  
  function refresh() {
    dataPromise = fetchData();  // New promise triggers re-render
  }
</script>

<button onclick={refresh}>Refresh</button>

{#await dataPromise}
  Loading...
{:then data}
  {data.value}
{/await}
✓ Completed