DEV Community

Jonathan Gamble
Jonathan Gamble

Posted on • Edited on

11 2

Async Fetching in Svelte 5

When you want to fetch something in Svelte, the recommended method is to put it in the load function.

I wrote an article about async fetching and why this could be important to work outside the load function.

Generally speaking, when SSR is not involved, you have better control of race conditions, error handling, and implementation outside the load function. While I agree in MOST situations you should use the load functions (with SvelteKit), this is not true for ALL situations.

Here is a simple resource function to handle this:

// resource.svelte.ts

export let resource = <T>(
    fn: () => Promise<T>,
    initialValue?: T
) => {

    const _rune = $state<{ value: T | undefined }>({
        value: initialValue
    });

    $effect(() => {
        fn().then((data) => {
            _rune.value = data;
        });
    });

    return _rune;
};
Enter fullscreen mode Exit fullscreen mode

And you would use it like so in your component:

import { resource } from '$lib/resource.svelte';
...
const todo = resource<Todo>(() =>
  fetch(`https://jsonplaceholder.typicode.com/todos/${id}`)
    .then((response) => response.json())
);
Enter fullscreen mode Exit fullscreen mode

And show the value with:

{todo.value}
Enter fullscreen mode Exit fullscreen mode

Similar Concepts in Other Frameworks

Now you can easily create a signal from an async resource! I hope something like this can get implemented in Svelte like $resource one day.

Demo: Vercel
Repo: GitHub

J

Update 2/2/25

It is good practice to handle the abort controller, so I added a version for that as well.

export let resource = <T>(
    getter: () => RequestInfo | URL,
    initialValue?: T
) => {

    const _rune = $state<{ value: T | undefined }>({
        value: initialValue
    });

    const controller = new AbortController();
    const { signal } = controller;

    $effect(() => {
        const url = getter();
        fetch(url, { signal })
            .then((response) =>
                response.json()
            )
            .then((data) => {
                _rune.value = data;
            });
        return () => controller.abort();
    });

    return _rune;
};
Enter fullscreen mode Exit fullscreen mode

This assumes you would call it:

const todo = resource<Todo>(() => 
    `https://jsonplaceholder.typicode.com/todos/${id}`
);

Enter fullscreen mode Exit fullscreen mode

There are many things you could do with this, maybe we will see something like this officially in Svelte.

J

Sentry blog image

How I fixed 20 seconds of lag for every user in just 20 minutes.

Our AI agent was running 10-20 seconds slower than it should, impacting both our own developers and our early adopters. See how I used Sentry Profiling to fix it in record time.

Read more

Top comments (6)

Collapse
 
mark_stein_bef16e6723b997 profile image
Mark Stein

This is awesome, thanks man

Collapse
 
webjose profile image
José Pablo Ramírez Vargas

As a correction, the load function and SSR only exist in Sveltekit, so maybe the title should say Sveltekit. Remember that one can do Svelte in non-Sveltekit projects.

Collapse
 
jdgamble555 profile image
Jonathan Gamble

Right, but this works in both Svelte and SvelteKit.

Collapse
 
webjose profile image
José Pablo Ramírez Vargas

There is no load function unless you're in Sveltekit.

Thread Thread
 
jdgamble555 profile image
Jonathan Gamble

Again, agreed, but you can use my resource function in both.

Collapse
 
devmercy profile image
Mercy

Works in both though

AWS Security LIVE!

Tune in for AWS Security LIVE!

Join AWS Security LIVE! for expert insights and actionable tips to protect your organization and keep security teams prepared.

Learn More

👋 Kindness is contagious

Immerse yourself in a wealth of knowledge with this piece, supported by the inclusive DEV Community—every developer, no matter where they are in their journey, is invited to contribute to our collective wisdom.

A simple “thank you” goes a long way—express your gratitude below in the comments!

Gathering insights enriches our journey on DEV and fortifies our community ties. Did you find this article valuable? Taking a moment to thank the author can have a significant impact.

Okay