# Fetching data from api with caching

This guide will walk you through the process of creating a basic stale-while-revalidate system using SvelteKit. This technique is particularly useful for improving performance by reducing unnecessary API calls and serving data more quickly.

### Understanding the Cache Structure

We'll start by creating a simple cache object:

{% tabs %}
{% tab title="+layout.server.js" %}
```javascript
const cache = {
  data: null,
  lastFetched: 0
};

const CACHE_DURATION = 60 * 1000; // 1 minute in milliseconds
```
{% endtab %}
{% endtabs %}

This cache object has two properties:

* `data`: Stores the cached data
* `lastFetched`: Timestamp of when the data was last fetched

We also define `CACHE_DURATION`, which sets how long the cached data remains valid (1 minute in this case).

{% hint style="info" %}
Adjusting the `CACHE_DURATION` allows you to balance between data freshness and performance. A longer duration reduces API calls but may serve slightly outdated data.
{% endhint %}

### Implementing the Load Function

Next, we'll create an asynchronous `load` function that manages the caching logic:

{% tabs %}
{% tab title="+layout.server.js" %}
```javascript
const cache = {
  data: null,
  lastFetched: 0
};

const CACHE_DURATION = 60 * 1000; // 1 minute in milliseconds

export async function load({ setHeaders }) {
  const now = Date.now();

  // Check if we have cached data and it's still fresh
  if (cache.data && now - cache.lastFetched < CACHE_DURATION) {
    // Serve cached data immediately
    return cache.data;
  }

  // Fetch fresh data
  const freshData = await fetchDataFromAPI();

  // Update cache
  cache.data = freshData;
  cache.lastFetched = now;

  // Set cache headers
  setHeaders({
    'Cache-Control': `max-age=0, s-maxage=${CACHE_DURATION / 1000}, stale-while-revalidate`
  });

  return freshData;
}
```
{% endtab %}
{% endtabs %}

This function does the following:

1. Checks if cached data exists and is still fresh
2. If cache is valid, returns cached data immediately
3. If cache is invalid or doesn't exist, fetches fresh data from the API
4. Updates the cache with fresh data
5. Sets appropriate cache headers
6. Returns the fresh data

{% hint style="warning" %}
The `setHeaders` function is framework-specific. Ensure your setup supports this method or adjust accordingly.
{% endhint %}

### Fetching Data from the API

The `fetchDataFromAPI` function is responsible for making the actual API call:

{% tabs %}
{% tab title="+layout.server.js" %}
```javascript
// Rest of code

async function fetchDataFromAPI() {
  const response = await fetch('https://admin.shentohendriks.nl/items/projects');
  const json = await response.json();
  return json;
}
```
{% endtab %}
{% endtabs %}

This function fetches data from a specific API endpoint and returns the parsed JSON response.

### Using the Cached Data in a Svelte Component

Finally, let's look at how to use this cached data in a Svelte component:

{% tabs %}
{% tab title="YourComponent.svelte" %}
```html
<script>
  export let data;
</script>

<img src={`https://admin.shentohendriks.nl/assets/${data.data[0].featuredImage}?key=compression`} alt="">
```
{% endtab %}
{% endtabs %}

This Svelte component receives the `data` prop, which contains the cached or freshly fetched data. It then uses this data to display an image.

{% hint style="info" %}
Ensure that the `data` structure matches what your component expects. In this case, it assumes `data.data.featuredImage` exists.
{% endhint %}

### Conclusion

This simple in-memory caching system can significantly improve your application's performance by reducing unnecessary API calls. Remember to adjust the cache duration and error handling to suit your specific needs.

{% hint style="warning" %}
While this example uses in-memory caching, for larger applications or server-side caching, consider using more robust caching solutions like Redis or Memcached.
{% endhint %}
