错误
错误是软件开发不可避免的事实。SvelteKit 根据错误发生的位置、错误类型以及传入请求的性质以不同的方式处理错误。
¥Errors are an inevitable fact of software development. SvelteKit handles errors differently depending on where they occur, what kind of errors they are, and the nature of the incoming request.
错误对象(Error objects)
¥Error objects
SvelteKit 区分预期错误和意外错误,默认情况下,两者都表示为简单的 { message: string }
对象。
¥SvelteKit distinguishes between expected and unexpected errors, both of which are represented as simple { message: string }
objects by default.
你可以添加其他属性,如 code
或跟踪 id
,如以下示例所示。(使用 TypeScript 时需要重新定义 Error
类型,如 类型安全 中所述)。
¥You can add additional properties, like a code
or a tracking id
, as shown in the examples below. (When using TypeScript this requires you to redefine the Error
type as described in type safety).
预期错误(Expected errors)
¥Expected errors
预期错误是使用从 @sveltejs/kit
导入的 error
助手创建的错误:
¥An expected error is one created with the error
helper imported from @sveltejs/kit
:
import { function error(status: number, body: App.Error): never (+1 overload)
Throws an error with a HTTP status code and an optional message.
When called during request handling, this will cause SvelteKit to
return an error response without invoking handleError
.
Make sure you’re not catching the thrown error, which would prevent SvelteKit from handling it.
error } from '@sveltejs/kit';
import * as module "$lib/server/database"
db from '$lib/server/database';
/** @type {import('./$types').PageServerLoad} */
export async function function load(event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>): MaybePromise<void | Record<string, any>>
load({ params: Record<string, any>
The parameters of the current route - e.g. for a route like /blog/[slug]
, a { slug: string }
object.
params }) {
const const post: {
title: string;
content: string;
} | undefined
post = await module "$lib/server/database"
db.function getPost(slug: string): Promise<{
title: string;
content: string;
} | undefined>
getPost(params: Record<string, any>
The parameters of the current route - e.g. for a route like /blog/[slug]
, a { slug: string }
object.
params.slug);
if (!const post: {
title: string;
content: string;
} | undefined
post) {
function error(status: number, body: App.Error): never (+1 overload)
Throws an error with a HTTP status code and an optional message.
When called during request handling, this will cause SvelteKit to
return an error response without invoking handleError
.
Make sure you’re not catching the thrown error, which would prevent SvelteKit from handling it.
error(404, {
App.Error.message: string
message: 'Not found'
});
}
return { post: {
title: string;
content: string;
}
post };
}
import { function error(status: number, body: App.Error): never (+1 overload)
Throws an error with a HTTP status code and an optional message.
When called during request handling, this will cause SvelteKit to
return an error response without invoking handleError
.
Make sure you’re not catching the thrown error, which would prevent SvelteKit from handling it.
error } from '@sveltejs/kit';
import * as module "$lib/server/database"
db from '$lib/server/database';
import type { type PageServerLoad = (event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
PageServerLoad } from './$types';
export const const load: PageServerLoad
load: type PageServerLoad = (event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
PageServerLoad = async ({ params: Record<string, any>
The parameters of the current route - e.g. for a route like /blog/[slug]
, a { slug: string }
object.
params }) => {
const const post: {
title: string;
content: string;
} | undefined
post = await module "$lib/server/database"
db.function getPost(slug: string): Promise<{
title: string;
content: string;
} | undefined>
getPost(params: Record<string, any>
The parameters of the current route - e.g. for a route like /blog/[slug]
, a { slug: string }
object.
params.slug);
if (!const post: {
title: string;
content: string;
} | undefined
post) {
function error(status: number, body: App.Error): never (+1 overload)
Throws an error with a HTTP status code and an optional message.
When called during request handling, this will cause SvelteKit to
return an error response without invoking handleError
.
Make sure you’re not catching the thrown error, which would prevent SvelteKit from handling it.
error(404, {
App.Error.message: string
message: 'Not found'
});
}
return { post: {
title: string;
content: string;
}
post };
};
这会引发 SvelteKit 捕获的异常,导致它将响应状态代码设置为 404 并渲染 +error.svelte
组件,其中 page.error
是作为 error(...)
的第二个参数提供的对象。
¥This throws an exception that SvelteKit catches, causing it to set the response status code to 404 and render an +error.svelte
component, where page.error
is the object provided as the second argument to error(...)
.
<script>
import { page } from '$app/state';
</script>
<h1>{page.error.message}</h1>
<script lang="ts">
import { page } from '$app/state';
</script>
<h1>{page.error.message}</h1>
Legacy mode
SvelteKit 2.12 中添加了
$app/state
。如果你使用的是早期版本或使用 Svelte 4,请改用$app/stores
。¥[!LEGACY]
$app/state
was added in SvelteKit 2.12. If you’re using an earlier version or are using Svelte 4, use$app/stores
instead.
如果需要,你可以向错误对象添加额外的属性...
¥You can add extra properties to the error object if needed...
function error(status: number, body: App.Error): never (+1 overload)
Throws an error with a HTTP status code and an optional message.
When called during request handling, this will cause SvelteKit to
return an error response without invoking handleError
.
Make sure you’re not catching the thrown error, which would prevent SvelteKit from handling it.
error(404, {
App.Error.message: string
message: 'Not found',
App.Error.code: string
code: 'NOT_FOUND'
});
...否则,为方便起见,你可以将字符串作为第二个参数传递:
¥...otherwise, for convenience, you can pass a string as the second argument:
error(404, { message: 'Not found' });
function error(status: number, body?: {
message: string;
} extends App.Error ? App.Error | string | undefined : never): never (+1 overload)
Throws an error with a HTTP status code and an optional message.
When called during request handling, this will cause SvelteKit to
return an error response without invoking handleError
.
Make sure you’re not catching the thrown error, which would prevent SvelteKit from handling it.
在 SvelteKit 1.x 中 你必须自己
throw
error
¥[!NOTE] In SvelteKit 1.x you had to
throw
theerror
yourself
意外错误(Unexpected errors)
¥Unexpected errors
意外错误是处理请求时发生的任何其他异常。由于这些可能包含敏感信息,因此不会向用户公开意外错误消息和堆栈跟踪。
¥An unexpected error is any other exception that occurs while handling a request. Since these can contain sensitive information, unexpected error messages and stack traces are not exposed to users.
默认情况下,意外错误会打印到控制台(或者,在生产中,打印到服务器日志),而向用户公开的错误具有通用形状:
¥By default, unexpected errors are printed to the console (or, in production, your server logs), while the error that is exposed to the user has a generic shape:
{ "message": "Internal Error" }
意外错误将通过 handleError
钩子,你可以在其中添加自己的错误处理 - 例如,将错误发送到报告服务,或返回变为 $page.error
的自定义错误对象。
¥Unexpected errors will go through the handleError
hook, where you can add your own error handling — for example, sending errors to a reporting service, or returning a custom error object which becomes $page.error
.
响应(Responses)
¥Responses
如果在 handle
内部或 +server.js
请求处理程序内部发生错误,SvelteKit 将根据请求的 Accept
标头以后备错误页面或错误对象的 JSON 表示进行响应。
¥If an error occurs inside handle
or inside a +server.js
request handler, SvelteKit will respond with either a fallback error page or a JSON representation of the error object, depending on the request’s Accept
headers.
你可以通过添加 src/error.html
文件来自定义后备错误页面:
¥You can customise the fallback error page by adding a src/error.html
file:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>%sveltekit.error.message%</title>
</head>
<body>
<h1>My custom error page</h1>
<p>Status: %sveltekit.status%</p>
<p>Message: %sveltekit.error.message%</p>
</body>
</html>
SvelteKit 将用其相应的值替换 %sveltekit.status%
和 %sveltekit.error.message%
。
¥SvelteKit will replace %sveltekit.status%
and %sveltekit.error.message%
with their corresponding values.
如果错误在渲染页面时发生在 load
函数内,SvelteKit 将渲染最接近发生错误位置的 +error.svelte
组件。如果错误发生在 +layout(.server).js
中的 load
函数内,则树中最近的错误边界是该布局上方(而不是旁边)的 +error.svelte
文件。
¥If the error instead occurs inside a load
function while rendering a page, SvelteKit will render the +error.svelte
component nearest to where the error occurred. If the error occurs inside a load
function in +layout(.server).js
, the closest error boundary in the tree is an +error.svelte
file above that layout (not next to it).
例外情况是当错误发生在根 +layout.js
或 +layout.server.js
内部时,因为根布局通常包含 +error.svelte
组件。在这种情况下,SvelteKit 使用后备错误页面。
¥The exception is when the error occurs inside the root +layout.js
or +layout.server.js
, since the root layout would ordinarily contain the +error.svelte
component. In this case, SvelteKit uses the fallback error page.
类型安全(Type safety)
¥Type safety
如果你使用的是 TypeScript 并且需要自定义错误的形状,则可以通过在应用中声明 App.Error
接口来实现(按照惯例,在 src/app.d.ts
中,尽管它可以存在于 TypeScript 可以 ‘see’ 的任何地方):
¥If you’re using TypeScript and need to customize the shape of errors, you can do so by declaring an App.Error
interface in your app (by convention, in src/app.d.ts
, though it can live anywhere that TypeScript can ‘see’):
declare global {
namespace App {
interface interface App.Error
Defines the common shape of expected and unexpected errors. Expected errors are thrown using the error
function. Unexpected errors are handled by the handleError
hooks which should return this shape.
Error {
App.Error.code: string
code: string;
App.Error.id: string
id: string;
}
}
}
export {};
此接口始终包含 message: string
属性。
¥This interface always includes a message: string
property.
进一步阅读(Further reading)
¥Further reading