最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Svelte: is there a way to cache the API result in a way that it won't trigger the API call every time the c

programmeradmin3浏览0评论

It could be that I'm typing the wrong things in Google and can't get a good answer.

Is there a "svelte recommended" way to store the value of a GET result, so that, on every refresh or link switch, the result in the store is used in the component until a timeout (where the API is called again)?

My purpose is to fetch blogposts from an external API and show them in a list but not on every refresh, or link switch.

My code:

<script>
  let posts = [];

  onMount(async () => {
    const res = await fetch(apiBaseUrl + "/blogposts");
    posts = await res.json();
  });
</script>

{#each posts as post}
  <h5>{post.title}</h5>
{/each}

In pseudo-code what I want:

if (store.blogposts.timeout === true){
  onMount(...);
  // renew component
} 

It could be that I'm typing the wrong things in Google and can't get a good answer.

Is there a "svelte recommended" way to store the value of a GET result, so that, on every refresh or link switch, the result in the store is used in the component until a timeout (where the API is called again)?

My purpose is to fetch blogposts from an external API and show them in a list but not on every refresh, or link switch.

My code:

<script>
  let posts = [];

  onMount(async () => {
    const res = await fetch(apiBaseUrl + "/blogposts");
    posts = await res.json();
  });
</script>

{#each posts as post}
  <h5>{post.title}</h5>
{/each}

In pseudo-code what I want:

if (store.blogposts.timeout === true){
  onMount(...);
  // renew component
} 
Share Improve this question edited Apr 9, 2024 at 13:06 Brian Tompsett - 汤莱恩 5,88372 gold badges61 silver badges133 bronze badges asked Sep 27, 2020 at 19:42 nucklenuckle 1191 gold badge1 silver badge9 bronze badges 3
  • Can you use svelte store to store a flag-variable, which tells when to reload posts? – grohjy Commented Sep 27, 2020 at 20:02
  • how would you set the flag? api-call, on a timer? for a timer you can use setTimeout setTimeout(() => { $timeout=true; }, 10 * 1000); in post.svelte – nuckle Commented Sep 28, 2020 at 9:13
  • @dagalti ’s answer is exactly what I had in mind. – grohjy Commented Sep 28, 2020 at 13:32
Add a comment  | 

3 Answers 3

Reset to default 15

you can use stores to achieve this. Initial page load fetch posts data from api and save in stores. Then use the posts data in further page mounts. Set timeout to true whenever you want to refresh data.

./stores.js

import {writable} from 'svelte/store';
export const posts = writable([]);
export const timeout = writable(false);

./posts.svelte

<script>
import {posts, timeout} from "./stores.js"

 onMount(async () => {
   if($posts.length<1 || $timeout == true){
     const res = await fetch(apiBaseUrl + "/blogposts");
     $posts = await res.json();
   }
});
</script>

  {#each $posts as post}
    <h5>{post.title}</h5>
  {/each}

When you refresh the page the posts in stores will clear. To avoid that use localstorage to cache data. pls check the below code. ./posts.svelte

<script>
let posts = [];
 
onMount(async () => { 
 posts = await getdata();
 } 
 
const getdata = async ()=>{
  // set cache lifetime in seconds
  var cachelife = 5000; 
   //get cached data from local storage
    var cacheddata = localStorage.getItem('posts'); 
    if(cacheddata){
     cacheddata = JSON.parse(cacheddata);
     var expired = parseInt(Date.now() / 1000) - cacheddata.cachetime > cachelife;
      }
    //If cached data available and not expired return them. 
    if (cacheddata  && !expired){
     return cacheddata.posts;
    }else{
    //otherwise fetch data from api then save the data in localstorage 
     const res = await fetch(apiBaseUrl + "/blogposts");
     var posts = await res.json();
     var json = {data: posts, cachetime: parseInt(Date.now() / 1000)}
     localStorage.setItem('posts', JSON.stringify(json));
     return posts;
    }
  }
 
{#each posts as post}
<h5>{post.title}</h5>
{/each}
    

svelte-query can help:

Svelte Query is often described as the missing data-fetching library for Svelte, but in more technical terms, it makes fetching, caching, synchronizing and updating server state in your Svelte applications a breeze.

note: svelte-query is abandoned and will be replaced with @tanstack/svelte-query

You can cache the data via the browser standard localStorage property. To clear the local storage, you can execute localStorage.clear() function in an interval:

  let data;
  let interval;

  onMount(async () => {
    // If data is cached, get it otherwise fetch it
    const cachedData = localStorage.getItem('cachedData');
    if (cachedData) {
      data = JSON.parse(cachedData);
    } else {
      data = await fetch('http://localhost:8080/blogposts')
        .then((response) => response.json())
        .then((dataJson) => dataJson)
        .catch((err) => console.warn(err));
      localStorage.setItem('cachedData', JSON.stringify(data));
    }

    // Clear the local storage after 3 seconds
    interval = setInterval(() => localStorage.clear(), 3000);
  });

Optionally, clean up the interval when the component is unmounted/destroyed. It is easily achieved by the clearInterval function:

  onDestroy(() => {
    clearInterval(interval);
  });

I have also created a simple API route to fetch from. The content of the routes/blogposts/+server.js file:

export function GET({ url }) {
  const data = [
    { title: 'Blog post 1', body: 'Body 1' },
    { title: 'Blog post 2', body: 'Body 2' },
    { title: 'Blog post 3', body: 'Body 3' }
  ];

  return new Response(JSON.stringify(data));
}

After that, you can fetch the data from the http://localhost:8080/blogposts URL.

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论