跳转到内容

Actions API 参考

添加于: astro@4.15.0

Action 帮助你构建一个类型安全的后端,你可以从客户端代码和 HTML 表单中调用它。所有用于定义和调用 Action 的工具函数都由 astro:actions 模块暴露。有关示例和使用说明,请参阅 Actions 指南

import {
ACTION_QUERY_PARAMS,
ActionError,
actions,
defineAction,
getActionContext,
getActionPath,
isActionError,
isInputError,
} from 'astro:actions';

类型: ({ accept, input, handler }) => ActionClient

一个用于在 src/actions/index.ts 中定义新的 actions 的工具函数。它接受一个 handler() 函数,其中包含在调用 Action 时要运行的服务器逻辑,以及一个可选的 input 属性,用于在运行时验证输入参数。

src/actions/index.ts
import { defineAction } from 'astro:actions';
import { z } from 'astro/zod';
export const server = {
getGreeting: defineAction({
input: z.object({
name: z.string(),
}),
handler: async (input, context) => {
return `Hello, ${input.name}!`
}
})
}

类型:(input: TInputSchema, context: ActionAPIContext) => TOutput | Promise<TOutput>

一个必要的函数,其中包含在调用 Action 时要运行的服务器逻辑。handler() 函数返回的数据将自动序列化并发送给调用者。

handler() 函数被调用时,接受用户输入作为其第一个参数。如果设置了 input 验证器,那么用户输入将在传递给 handler() 前进行验证。第二个参数是 Astro 的 context 对象的一个子集

返回值使用 devalue 库 进行解析。它支持 JSON 值,以及 Date(), Map(), Set(), 或 URL() 的实例。

类型:ZodType | undefined

一个可选的属性,接受一个 Zod 验证器 (EN)(例如,Zod 对象,Zod 可区分联合),用于在运行时验证处理程序的输入。如果 action 验证失败,将返回 BAD_REQUEST 错误 并跳过 handler

如果省略 input,则 handler 将接收 JSON 请求的 unknown 类型的输入,以及表单请求的 FormData 类型。

类型:"form" | "json"
默认值:json

定义某个 action 所期望的格式:

  • 当你的 action 接收 Formdata 时使用 form
  • 在所有其他情况下,使用默认的 json

当你的 action 接受表单输入时,z.object() 验证器会自动将 FormData 解析为类型化对象。所有 Zod 验证器均受支持,可用于验证你的输入。

在 Actions 指南中 了解如何将验证器与表单输入一起使用,包括示例用法和特殊输入处理。

类型:Record<string, ActionClient>

一个包含了你所有的 action 的对象,action 名称作为键,并关联到一个用于调用该 action 的函数。

src/pages/index.astro
---
---
<script>
import { actions } from 'astro:actions';
async () => {
const { data, error } = await actions.myAction({ /* ... */ });
}
</script>

为了让 Astro 识别此属性,你可能需要重启开发服务器或 运行 astro sync 命令s + enter车)。

类型:(error?: unknown) => boolean

一个常用于检查 ActionError 是否是输入验证错误的工具函数。当 input 验证器是 z.object() 时,输入错误包括一个 fields 对象,其中错误消息按名称分组。

更多关于使用 isInputError() 的信息,请参见 表单输入错误指南

类型:(error?: unknown) => boolean

一个用于检查你的 action 是否引发了 handler 属性 中的 ActionError 的工具函数。这在缩小泛型错误的类型时很有用。

src/pages/index.astro
---
---
<script>
import { isActionError, actions } from 'astro:actions';
async () => {
const { data, error } = await actions.myAction({ /* ... */ });
if (isActionError(error)) {
// 处理 action 特定的错误
console.log(error.code);
}
}
</script>

ActionError 构造函数常用于在 handler() 函数中抛出错误。它接受一个 code 属性,描述发生的错误(例如:"UNAUTHORIZED"),以及一个可选的 message 属性,提供进一步的细节。

下面的示例在用户未登录时创建一个新的 ActionError

src/actions/index.ts
import { defineAction, ActionError } from "astro:actions";
export const server = {
getUserOrThrow: defineAction({
accept: 'form',
handler: async (_, { locals }) => {
if (locals.user?.name !== 'florian') {
throw new ActionError({
code: 'UNAUTHORIZED',
message: 'Not logged in',
});
}
return locals.user;
},
}),
}

你还可以使用 ActionError 在处理某个 action 的结果时缩小错误类型范围:

src/pages/index.astro
---
---
<script>
import { ActionError, actions } from 'astro:actions';
async () => {
const { data, error } = await actions.myAction({ /* ... */ });
if (error instanceof ActionError) {
// 处理 action 特定的错误
console.log(error.code);
}
}
</script>

类型:ActionErrorCode

定义一个 HTTP 状态码 的人类可读版本。

类型: string

一个用于描述错误的可选参数。(例如:“用户必须登录。“)

类型:string

用于传递堆栈跟踪的可选属性。

类型:(context: APIContext) => AstroActionContext

添加于: astro@5.0.0

一个从你的中间件处理程序中调用的函数,用于检索有关入站 action 请求的信息。此函数返回一个 action 对象,其中包含有关请求的信息,以及 setActionResult()serializeActionResult() 函数,用于以编程方式设置 Astro.getActionResult() 返回的值。

getActionContext() 运行你使用中间件以编程方式获取和设置 action 结果,允许你从 HTML 表单中持久化 action 结果,通过添加安全检查来限制 action 请求,等等。

src/middleware.ts
import { defineMiddleware } from 'astro:middleware';
import { getActionContext } from 'astro:actions';
export const onRequest = defineMiddleware(async (context, next) => {
const { action, setActionResult, serializeActionResult } = getActionContext(context);
if (action?.calledFrom === 'form') {
const result = await action.handler();
setActionResult(action.name, serializeActionResult(result));
}
return next();
});

类型:{ calledFrom: “rpc” | “form”; name: string; handler: () => Promise<SafeResult>; } | undefined

一个包含有关入站 action 请求的信息的对象。它可以从 getActionContext() 中获取,并提供 action 名称、handler 以及 action 是否是从客户端 RPC 函数(例如 actions.newsletter())或 HTML 表单 action 中调用的。

src/middleware.ts
import { defineMiddleware } from 'astro:middleware';
import { getActionContext } from 'astro:actions';
export const onRequest = defineMiddleware(async (context, next) => {
const { action, setActionResult, serializeActionResult } = getActionContext(context);
if (action?.calledFrom === 'rpc' && action.name.startsWith('private')) {
// 检查是否有有效的会话令牌
}
// ...
});

类型:"rpc" | "form"

该 action 是通过 RPC 函数调用还是通过 HTML 表单的 action 调用。

类型:string

action 的名称。用于在重定向期间跟踪 action 结果的来源。

类型:() => Promise<SafeResult>

以编程方式调用一个 action 以获取结果。

类型: (actionName: string, actionResult: SerializedActionResult) => void

一个以编程方式设置中间件中 Astro.getActionResult() 返回值的函数。它接受 action 名称和由 serializeActionResult() 序列化的 action 结果。从中间件调用此函数将禁用 Astro 自身的 action 结果处理。

当从 HTML 表单中调用 action 以持久化和加载结果时,这很有用。

src/middleware.ts
import { defineMiddleware } from 'astro:middleware';
import { getActionContext } from 'astro:actions';
export const onRequest = defineMiddleware(async (context, next) => {
const { action, setActionResult, serializeActionResult } = getActionContext(context);
if (action?.calledFrom === 'form') {
const result = await action.handler();
// ... 处理 action 结果
setActionResult(action.name, serializeActionResult(result));
}
return next();
});
请参阅 高级会话指南 以查看使用 Netlify Blob 的示例实现。

类型:(res: SafeResult) => SerializedActionResult

将 action 结果序列化为 JSON 以进行持久化。这对于正确处理 MapDate 等非 JSON 返回值以及 ActionError 对象是必需的。

要把序列化后的 action 结果传递给 setActionResult() 时调用此函数:

src/middleware.ts
import { defineMiddleware } from 'astro:middleware';
import { getActionContext } from 'astro:actions';
export const onRequest = defineMiddleware(async (context, next) => {
const { action, setActionResult, serializeActionResult } = getActionContext(context);
if (action) {
const result = await action.handler();
setActionResult(action.name, serializeActionResult(result));
}
// ...
});

类型:(res: SerializedActionResult) => SafeResult

反转 serializeActionResult() 的效果,并将 action 结果返回到其原始状态。这对于访问序列化的 action 结果上的 dataerror 对象很有用。

类型:(action: ActionClient) => string

添加于: astro@5.1.0

一个工具函数,接受一个 action 并返回一个 URL 路径,以便你可以直接将 action 调用作为 fetch() 操作执行。这允许你在调用 action 时提供诸如自定义标头之类的详细信息。然后,你可以根据需要 处理自定义格式化的返回数据,就像直接调用 action 一样。

下面的示例展示了如何调用一个定义的 like action,传递 Authorization 标头和 keepalive 选项:

src/components/my-component.astro
<script>
import { actions, getActionPath } from 'astro:actions'
await fetch(getActionPath(actions.like), {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer YOUR_TOKEN'
},
body: JSON.stringify({ id: 'YOUR_ID' }),
keepalive: true
})
</script>

下面的示例展示了如何使用 sendBeacon API 调用相同的 like action:

src/components/my-component.astro
<script>
import { actions, getActionPath } from 'astro:actions'
navigator.sendBeacon(
getActionPath(actions.like),
new Blob([JSON.stringify({ id: 'YOUR_ID' })], {
type: 'application/json'
})
)
</script>

类型:{ actionName: string, actionPayload: string }

一个包含 Astro 在处理表单 action 提交时内部使用的查询参数名称的对象。

当你使用 action 提交表单时,以下查询参数会被添加到 URL 中以跟踪该 action 调用:

  • actionName - 包含正在调用的 action 名称的查询参数
  • actionPayload - 包含序列化表单数据的查询参数

当你需要在表单提交后清理 URL 时,此常量非常有用。例如,在重定向期间,你可能希望移除与 action 相关的查询参数:

src/pages/api/contact.ts
import type { APIRoute } from "astro";
import { ACTION_QUERY_PARAMS } from 'astro:actions'
export const GET: APIRoute = ({ params, request }) => {
const link = request.url.searchParams;
link.delete(ACTION_QUERY_PARAMS.actionName);
link.delete(ACTION_QUERY_PARAMS.actionPayload);
return redirect(link, 303);
};
import type {
ActionAPIContext,
ActionClient,
ActionErrorCode,
ActionInputSchema,
ActionReturnType,
SafeResult,
} from 'astro:actions';

Astro 上下文对象 的子集。以下属性不可用:callActiongetActionResultpropsredirect

类型:

  • (input?: any) => Promise<SafeResult>
  • { queryString?: string; orThrow: (input?: any) => Promise<Awaited<TOutput>>; }

表示要在客户端调用的 action。你可以将其作为一个函数使用,该函数接收输入数据并返回一个包含 action 结果或验证错误的 SafeResult 对象 的 Promise。

下面的示例展示了在点赞计数增加失败时如何使用 if 语句提供错误处理:

src/pages/posts/post-1.astro
---
---
<!-- 你的模板代码 -->
<script>
import { actions } from 'astro:actions';
const post = document.querySelector('article');
const button = document.querySelector('button');
button?.addEventListener('click', async () => {
const { data: updatedLikes, error } = await actions.likePost({ postId: post?.id });
if (error) {
/* 处理错误 */
}
})
</script>

或者,你可以将其作为一个对象来使用,以便访问 queryString 和另一个叫做 orThrow() 的方法。

类型:string

可用于构建表单 action URL 的 action 的字符串表示。当你的表单组件在多个地方使用但提交时需要重定向到不同 URL 时,这会很有用。

下面的示例使用 queryString 构建一个 URL,该 URL 将通过自定义属性传递给表单的 action 属性:

src/pages/postal-service.astro
---
import { actions } from 'astro:actions';
import FeedbackForm from "../components/FeedbackForm.astro";
const feedbackUrl = new URL('/feedback', Astro.url);
feedbackUrl.search = actions.myAction.queryString;
---
<FeedbackForm sendTo={feedbackUrl.pathname} />

类型:(input?: any) => Promise<Awaited<TOutput>>

一种在失败时抛出错误而不是返回错误的方法。当你更希望使用异常而不是错误处理时,这很有用。

下面的示例在递增点赞数失败时使用 orThrow() 来跳过错误处理:

src/pages/posts/post-1.astro
---
---
<!-- 你的模板代码 -->
<script>
import { actions } from 'astro:actions';
const post = document.querySelector('article');
const button = document.querySelector('button');
button?.addEventListener('click', async () => {
const updatedLikes = await actions.likePost.orThrow({ postId: post?.id });
})
</script>

类型:string

由 IANA 定义 的一组标准 HTTP 状态代码的联合类型,使用可读的人类版本作为大写字符串并以下划线分隔(例如 BAD_REQUESTPAYLOAD_TOO_LARGE)。

类型:ZodType

添加于: astro@5.16.0

一种工具类型,它基于 Zod 模式自动推断某 action 作输入的 TypeScript 类型。这在你希望在自己的类型定义中将某个 action 的 input 验证器类型 作为对象引用时非常有用。

当未提供 input 验证器 时,返回 never

下面的示例在名为 contact 的 action 上使用 ActionInputSchema 来:

  • 检索该 action 输入的 Zod 模式类型。
  • 检索该 action 验证器所期望的输入类型。
src/components/Form.astro
---
import { actions, ActionInputSchema } from 'astro:actions';
import { z } from 'astro/zod';
type ContactSchema = ActionInputSchema<typeof actions.contact>;
type ContactInput = z.input<ContactSchema>;
---

类型:Awaited<ReturnType<ActionHandler>>

一种工具类型,用于从 action handler 中提取输出类型。它会解包 Promise(如果处理器是异步的)和 ReturnType,以提供 实际的输出类型。如果你需要在自己的类型定义中引用某个 action 的输出类型,这会很有用。

下面的示例使用 ActionReturnType 来获取名为 contact 的 action 的预期输出类型:

src/components/Form.astro
---
import { actions, ActionReturnType } from 'astro:actions';
type ContactResult = ActionReturnType<typeof actions.contact>;
---

类型:{ data: TOutput, error: undefined } | { data: undefined, error: ActionError }

表示 action 调用的结果:

  • 成功时,data 包含 action 的输出,errorundefined
  • 失败时,error 包含一个 ActionError,其中包含验证错误或运行时错误,dataundefined
贡献 社区 赞助