在 svelte 中等待来自加载函数的数据时渲染标记

问题描述 投票:0回答:3

我知道有一些关于此的讨论。例如这里:

https://github.com/sveltejs/kit/discussions/8640

但是,我还是没有完全理解。我有一个

+page.svelte
和相应的
+page.js
文件。在
+page.js
文件中,我获取了一些外部数据。这可能需要一点时间。在这样做的同时,我想让用户至少知道数据已被获取或其他什么。或者甚至渲染不依赖于数据本身的标记。

+page.js
中的代码看起来像这样:

import { fetchAllData } '$lib/utils';

export async function load({ fetch, url }) {
    let id = url.searchParams.get('id');
    let data = fetchAllData(id, fetch);
    return { data };
}

我想知道我是否/如何可以在

+page.svelte

中做这样的事情
<script>
    export let data;
</script>

{#await data}
    waiting
{:then d}
    respo
{/await}
javascript async-await promise svelte
3个回答
3
投票

虽然 H.B. 的答案在技术上是正确的,但我认为

+page.js
不是适合您的用例的正确工具。

使用

+page.js
而不是在
onMount
回调中获取的全部目的是避免“加载”问题。

让我解释一下,

+page.js
被执行:

  1. 在服务器端用于初始路线,例如在地址栏中输入网址,或点击浏览器刷新按钮。
  2. 在客户端进行后续的现场导航,例如点击页面A上的链接导航到页面B,然后在客户端执行B的
    +page.js
    (页面A和B都需要是同一个SvelteKit项目内的路由)

对于第一种情况,数据加载是在服务器上处理的,在数据加载之前页面甚至不会渲染。因此,用户将不得不等待一段时间,同时盯着空白屏幕。如果这需要很长时间,他们可能会觉得您的网站很慢。

对于第二种情况,数据加载实际上是在页面 A 中处理的,而不是页面 B 中。就像用户单击页面 A 上的链接,但不会导航到页面 B 直到

+page.js
完成执行。因此,如果花费很长时间,用户会停留在页面 A,并且可能会认为他们错过了点击该链接的机会,并且可能会再次点击它。

了解这种行为应该可以帮助您确定

+page.js
是否是解决您问题的正确工具。

我的建议是,

  • 对于需要合理时间来加载数据的正常用例,请使用
    +page.js
    ,您不必担心加载状态。
  • 对于加载数据需要非常长时间的特殊用例,那么您甚至不应该使用
    +page.js
    。您应该只使用旧的
    onMount(() => fetch(...))
    并显示加载指示器以让用户保持耐心。

+page.js
专为“正常用例”而设计,无需费力使用该工具,只需选择正确的工具即可。


3
投票

编辑:在 v2 中,不会自动等待顶级承诺。

data
中的顶级承诺在渲染页面之前会自动等待,您必须将承诺分配给更深层次的属性,例如

return { deferred: { data: fetchAllData(id, fetch) } }
{#await data.deferred.data}

文档

(建议重命名,

data
不是很有描述性,并且页面数据变量也已经被称为
data
。)


0
投票

您几乎已经回答了自己的问题,这是他们官方文档的片段(下面的链接),因此效果非常好。

<script>
    let promise = getRandomNumber();

    async function getRandomNumber() {
        const res = await fetch(`/tutorial/random-number`);
        const text = await res.text();

        if (res.ok) {
            return text;
        } else {
            throw new Error(text);
        }
    }

    function handleClick() {
        promise = getRandomNumber();
    }
</script>

<button on:click={handleClick}>
    generate random number
</button>

{#await promise}
    <p>...waiting</p>
{:then number}
    <p>The number is {number}</p>
{:catch error}
    <p style="color: red">{error.message}</p>
{/await}

https://svelte.dev/examples/await-blocks

这是一个例子。我基于你的代码:-

https://svelte.dev/repl/e81ca49d739b4f86a2753aed59443467?version=3.59.1

© www.soinside.com 2019 - 2024. All rights reserved.