<svelte:boundary>
<svelte:boundary onerror={handler}>...</svelte:boundary>
[!NOTE] 该特性在 5.3.0 中新增
边界(boundaries)让你可以将应用的某些部分"隔离"起来,从而能够:
- 提供在
await表达式首次解析时应当显示的 UI - 处理在渲染过程中或运行 effects 时发生的错误,并提供错误发生时应当渲染的 UI
如果边界处理了某个错误(通过 failed 代码片段或 onerror 处理器,或两者兼具),它已有的内容会被移除。
[!NOTE] 在渲染过程之外发生的错误(例如,在事件处理器中,或在
setTimeout或异步工作之后)_不会_被错误边界捕获。
属性
要让边界发挥作用,必须提供以下一个或多个属性。
pending
当边界首次创建时,该代码片段会被显示,并会一直可见,直到边界内部的所有 await 表达式都已解析(演示):
<svelte:boundary>
<p>{await delayed('hello!')}</p>
{#snippet pending()}
<p>loading...</p>
{/snippet}
</svelte:boundary>
对于随后的异步更新,pending 代码片段_不会_被显示——对于这些,你可以使用 $effect.pending()。
[!NOTE] 在playground 中,你的应用被渲染在一个带有空
pending代码片段的边界内部,这样你就可以直接使用await而无需自己创建边界。
failed
如果提供了 failed 代码片段,当边界内部抛出错误时,它会被渲染,并带有 error 和一个用于重建内容的 reset 函数(演示):
<svelte:boundary>
<FlakyComponent />
{#snippet failed(error, reset)}
<button onclick={reset}>oops! try again</button>
{/snippet}
</svelte:boundary>
[!NOTE] 与传递给组件的代码片段 一样,
failed代码片段既可以显式作为属性传递……<svelte:boundary {failed}>...</svelte:boundary>……也可以像上面的示例那样,通过直接在边界内部声明来隐式传递。
onerror
如果提供了 onerror 函数,它会被调用,并传入相同的 error 和 reset 两个参数。这对于使用错误上报服务来追踪错误很有用……
<svelte:boundary onerror={(e) => report(e)}>
...
</svelte:boundary>
……或者在边界自身之外使用 error 和 reset:
<script>
let error = $state(null);
let reset = $state(() => {});
function onerror(e, r) {
error = e;
reset = r;
}
</script>
<svelte:boundary {onerror}>
<FlakyComponent />
</svelte:boundary>
{#if error}
<button onclick={() => {
error = null;
reset();
}}>
oops! try again
</button>
{/if}
如果 onerror 函数内部发生了错误(或者你重新抛出了错误),那么如果有父级边界,它会由父级边界来处理。
使用 transformError
默认情况下,错误边界在服务端没有任何效果——如果在渲染期间发生错误,整个渲染都会失败。
自 5.51 起,你可以通过使用一个带有 failed 代码片段的边界,并传入一个 transformError 函数调用 render(...) 来控制这一行为。
[!NOTE] 如果你是通过像 SvelteKit 这样的框架来使用 Svelte,你很可能无法直接访问
render(...)调用——框架必须代为配置transformError。SvelteKit 将在近期通过handleError钩子添加对此的支持。
transformError 函数必须返回一个可被 JSON 序列化的对象,该对象将被用于渲染 failed 代码片段。这个对象会被序列化,并用于在浏览器中 hydrate 该代码片段:
import { render } from 'svelte/server';
import App from './App.svelte';
const { head, body } = await render(App, {
transformError: (error) => {
// log the original error, with the stack trace...
console.error(error);
// ...and return a sanitized user-friendly error
// to display in the `failed` snippet
return {
message: 'An error occurred!'
};
}
});
如果 transformError 抛出(或重新抛出)了一个错误,render(...) 作为一个整体会以该错误而失败。
[!NOTE] 在服务端渲染期间发生的错误,其
message和stack中可能包含敏感信息。建议对其做脱敏处理,而不是直接原样发送到浏览器。
如果边界带有一个 onerror 处理器,它在 hydrate 时会被调用,并传入反序列化后的错误对象。
mount 和 hydrate 函数同样接受一个 transformError 选项,该选项默认为恒等函数。与 render 一样,此函数会在渲染时错误被传递给 failed 代码片段或 onerror 处理器之前对其做转换。