Skip to main content

await

截至 Svelte 5.36,您可以在组件中三个之前不可用的位置使用await关键字:

  • 在组件的最高级别中 脚本
  • 内部 $derived(...) 声明
  • 在您的标记内

此功能目前处于实验阶段,您必须通过添加 experimental.async 选项来启用,通常在您 配置 Svelte 时进行,通常在 svelte.config.js 中:

svelte.config
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);

https://svelte.dev/docs/svelte/$derived

@paramexpression The derived state expression
$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);

https://svelte.dev/docs/svelte/$derived

@paramexpression The derived state expression
$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.prebeforeUpdate 之前运行,这意味着在 非常罕见的情况下,可能会更新一个本应不再存在的块,但仅当你在效果内部更新状态时,这应该避免

Edit this page on GitHub llms.txt

previous next