4

I have a page (a dynamic route) where I am fetching data from an API in the load function. What is the correct way to show a loading indicator till the data is fetched. Things I have tried:

  1. Using await block. I return a promise to fetch function and then in the normal script tag, I export a promise variable. I then resolve this promise manually after manipulating the data.
<script context="module">
  export async function load({ fetch, page }) {   
    let collectionId = page.params.id;    
    let endpoint = url;   
    const promise = fetch(endpoint);  
    return {props:{promise}}; 
  }
</script>

then in normal script tag

<script>
export let promise = new Promise(() => '');

promise = new Promise((resolve, reject) => {
    promise.then(function (response) {
      if(response.ok){
        console.log('response');
        response.json().then(function (json) {
          console.log('data in promise');
          console.log(json);
          let posts = json.map((post) => new Post(post));
          posts = posts.sort(function (a, b) {
            return a.id - b.id;
          });
          resolve(posts);
        });
      }else{
        response.text().then((text)=>reject(text));
      }
    });
});
</script>

then in HTML

{#await promise}
    <Shimmer items="3" />
{:then posts}
    <Cards data={posts} />
{:catch error}
    <Error message={error}/>
{/await}

This works fine the first time, I am guessing, this works when the page is rendered server side. But on subsequent calls, my promise resolution logic doesn't get called and I receive promise directly in my await block, where there is no logic to manipulate it.

  1. I export a variable to receive final processed data from the load function and in HTML, I try to display the loading indicator till this variable is undefined using {if} block. This works for the first time when the variable is actually undefined, but on subsequent calls, only the value of this variable changes but it is never undefined.

let posts;

{#if posts===undefined}
Loading...
{:else}
{posts}
{/if}
4

2 回答 2

7

所以我通过使用navigating商店解决了这个问题。我不知道这是否是正确的方法。但这对我来说似乎工作得很好。

在页面被服务器渲染并且控制传递到客户端之后,navigating当从一个页面导航到另一个页面时,store 为 true。(阅读更多)

所以在我的 __layout.svelte 中,我正在做

{#if $navigating} Loading... {:else} Content {/if}

于 2021-07-10T05:45:02.983 回答
0

以这种方式在模块中使用load()函数的好处之一是您不需要使用任何类型的微调器或等待数据,因为函数在创建组件之前运行。在数据准备好之前,页面实际上不会加载。从文档:

[加载功能] 允许您获取页面的数据,而无需(例如)显示加载微调器并在 onMount 中获取数据。

所以在你的情况下,只需使用

<script>
    export let promise;
</script>

足够的。无论您是否是第一次访问该页面,promise 变量中的数据都是可用的,而无需在其上使用任何 await 或 promise 逻辑。它就像使用if (promise)来查看您是否获得数据一样简单。

于 2021-06-29T06:09:01.773 回答