await
截至 Svelte 5.36,您可以在组件中三个之前不可用的位置使用await关键字:
- 在组件的最高级别中
脚本 - 内部
$derived(...)声明 - 在您的标记内
此功能目前处于实验阶段,您必须通过添加 experimental.async 选项来启用,通常在您 配置 Svelte 时进行,通常在 svelte.config.js 中:
export default {
compilerOptions: {
experimental: {
async: boolean;
};
}
compilerOptions: {
experimental: {
async: boolean;
}
experimental: {
async: booleanasync: true
}
}
};实验标志将在 Svelte 6 中移除。
边界
当前,您只能在具有 await 的 <svelte:boundary> 内部使用一个 pending 片段:
<svelte:boundary>
<MyApp />
{#snippet pending()}
<p>loading...</p>
{/snippet}
</svelte:boundary>此限制将在 Svelte 支持异步服务器端渲染后解除(见注意事项)。
[!注意] 在沙盒中,您的应用在一个带有空挂起代码片段的边界内渲染,这样您就可以使用
await而无需创建一个。
同步更新
當一個await表達式依賴於特定的狀態時,該狀態的變化將不會在 UI 中反應,直到異步操作完成,這樣 UI 就不會處於不一致的狀態。換句話說,在像這個...這樣的例子中。
<script>
let a = $state(1);
let b = $state(2);
async function add(a, b) {
await new Promise((f) => setTimeout(f, 500)); // artificial delay
return a + b;
}
</script>
<input type="number" bind:value={a}>
<input type="number" bind:value={b}>
<p>{a} + {b} = {await add(a, b)}</p>...如果您增加a,则<p>的内容将不会立即更新为读取此内容—
2 + 2 = 3
— 相反,当 add(a, b) 解析时,文本将更新为 2 + 2 = 4。
更新可以重叠——快速更新将在用户界面中反映出来,而较早的慢速更新仍在进行中。
并发
Svelte 会尽可能并行地执行异步操作。例如,如果你在标记中有两个await表达式...
<p>{await one()}</p>
<p>{await two()}</p>...两个函数将同时运行,因为它们是独立的表达式,尽管它们在视觉上是连续的。
这不适用于您代码中的 await 表达式,也不适用于 <script> 内部或异步函数内部 — 这些运行方式与其他异步 JavaScript 一样。例外的是,独立的 $derived 表达式将独立更新,尽管它们在首次创建时将按顺序运行:
// these will run sequentially the first time,
// but will update independently
let let a: numbera = function $derived<number>(expression: number): number
namespace $derived
Declares derived state, i.e. one that depends on other state variables.
The expression inside $derived(...) should be free of side-effects.
Example:
let double = $derived(count * 2);
$derived(await function one(): Promise<number>one());
let let b: numberb = function $derived<number>(expression: number): number
namespace $derived
Declares derived state, i.e. one that depends on other state variables.
The expression inside $derived(...) should be free of side-effects.
Example:
let double = $derived(count * 2);
$derived(await function two(): Promise<number>two());[注意] 如果您编写如下代码,请期待 Svelte 给您一个
await_waterfall警告
指示加载状态
除了最近的边界待处理片段外,您还可以使用$effect.pending()来表示异步工作正在进行中。
您也可以使用settled()来获取一个当当前更新完成时解决的承诺:
import { function tick(): Promise<void>Returns a promise that resolves once any pending state changes have been applied.
tick, import settledsettled } from 'svelte';
async function function onclick(): Promise<void>onclick() {
let updating: booleanupdating = true;
// without this, the change to `updating` will be
// grouped with the other changes, meaning it
// won't be reflected in the UI
await function tick(): Promise<void>Returns a promise that resolves once any pending state changes have been applied.
tick();
let color: stringcolor = 'octarine';
let answer: numberanswer = 42;
await import settledsettled();
// any updates affected by `color` or `answer`
// have now been applied
let updating: booleanupdating = false;
}错误处理
错误在 await 表达式中会冒泡到最近的 错误边界。
注意事项
作为一个实验性功能,如何处理 await(以及相关的 API 如$effect.pending())的细节,以及这些变更是否会导致破坏性更改(尽管我们打算将此类变更控制在最小范围内),在非 semver 主版本发布之外,可能会发生变化。
当前,服务器端渲染是同步的。如果在 SSR 过程中遇到具有<svelte:boundary>和pending片段的,只有pending片段会被渲染。
破坏性变更
效果在启用 experimental.async 选项时以略有不同的顺序运行。具体来说,像 block 效果如 {#if ...} 和 {#each ...} 现在会在同一组件中的 $effect.pre 或 beforeUpdate 之前运行,这意味着在 非常罕见的情况下,可能会更新一个本应不再存在的块,但仅当你在效果内部更新状态时,这应该避免。
Edit this page on GitHub llms.txt