在等待一段时间后显示加载程序的巧妙方法是什么?

What is a svelte approach to showing a loader after a time of waiting?

为了在等待 Web 请求响应时显示加载微调器,我将在我的微调器组件中使用以下非常简单的 if 语句:

{#if waitingForAPIResponse}
    <Spinner></Spinner>
{/if}

什么是仅在等待 200 毫秒后才显示 Spinner 组件的好方法?我直觉上想设置一个计时器,但我敢打赌有更好的方法。

我想没有最简单的方法可以在 setTimeout 的 x 秒后生成事件。所以我只使用另一个变量 timerOK 最初是 false 和 200ms true:

<script>
    import {onMount} from 'svelte'

    let response = null
    let timerOK = false
    
    $: isLoading = !(response && timerOK)
    
    onMount(() => {
        setTimeout(() => { 
            timerOK = true
        }, 1200)

        fetch('...').then(callResponse => {
            // do your stuffs
            response = 'OK'
        })
    })
</script>

{#if isLoading}
    ...Loading
{:else}
    {response}
{/if}

看看REPL

最动态的方法是添加另一个承诺。

<script>
    const wait = () => new Promise((res) => setTimeout(res , 1000))
</script>

{#await APIRequest}
    {#await wait()}
        <span>Not going to take long</span>
    {:then a}
        <span>Taking a while</span>
  {/await}
{:then data}
    ...
{/await}

这里重要的是 'inner await' 调用了一个函数,这将在每次呈现时触发创建一个新的承诺(例如,如果由于某种原因您重新触发 APIRequest)。

这也可以扩展为通过简单地将参数传递给 wait:

来灵活地等待多长时间
const wait = delay => new Promise((res) => setTimeout(res, delay))

您还可以在 Loader 组件中包含等待逻辑

<!-- Loader.svelte -->

<script>
    import { onDestroy } from "svelte";

    let show = false;
    const timeoutId = setTimeout(()=>show=true, 400);
    onDestroy(()=>clearTimeout(timeoutId));
</script>

{#if show}
    <Spinner/>
{/if}

然后像这样使用它

{#if waitingForAPIResponse}
    <Loader/>
{/if}

在超时完成之前不会呈现 <Spinner/>


您可以使用这种方法自定义很多东西。
您可以使用 slots

使内部 <Spinner/> 动态化
...

{#if show}
    <slot>
        <Spinner/>
    </slot>
{/if}

现在您可以像这样使用它了

{#if waitingForAPIResponse}
    <Loader>
        <Spinnerv2/>
    </Loader>
{/if}

当然,它不再是 "Loader",更像是 "DelayedRenderer"