关于Server Actions统一返回
背景
之前在Next项目中用Server Actions时,并没有考虑统一约定,进行明确的返回。基本上返不返回完全就是俗称的看情况......然后我就吸取教训了,遇到了各种神奇的bug,而且往往都没有警告。但是它会反馈在交互上,比如跳转不了、收不到提示(因为报错了但是又收不到error或者warning)。刚开始还认认真真改bug,后面越想越不对,都是差不多的页面,怎么有的有bug有的没bug?仔细检查,有的action方法因为需要我返回了,有的没有返回就比较随意,后面痛定思痛,决定重构代码。
解决思路
1、将actions.ts 的各个方法改为标准化返回对象,并加入 try/catch 与一致的校验返回:
示例:
createProject: Promise<{ ok: boolean; id?: string; message?: string }>
2、统一类型别名:
将多个地方的返回 type ActionResult = { ok: boolean; message?: string; id?: string }抽离出来,并在各个模块 Action 复用,提升一致性与可读性。
export type ActionResult = {
ok: boolean;
message?: string;
};
export type ActionResultWithId = ActionResult & {
id?: string;
};
export type ActionResultData<T extends object = object> = ActionResult & T;
3、进行明确的类型标注:
loginAction: 返回类型可标注为Promise<ActionResult | void>。logoutAction: 标注为Promise<void>。
示例:
export async function createSomething(formData: FormData): Promise<ActionResultWithId> {
try {
// 验证、写入 DB 等
const created = await db.create(...);
// 可选:revalidatePath(...)
return { ok: true, id: created.id };
} catch (err: unknown) {
const msg = err instanceof Error ? err.message : '操作失败';
console.error('createSomething error:', err);
return { ok: false, message: msg };
}
}
总结
server actions 推荐并且通常需要有明确的返回值。没有返回值会导致客户端收到 undefined,容易引发警告、类型错误或难以排查的 bug。因为调用方会 await 或读取返回值,如果返回 undefined,会在访问属性时抛出错误或导致不可预期行为。明确返回类型(如 ActionResult/ActionResultWithId)能让 TypeScript、编辑器和调用方都清楚预期格式,减少运行时错误。 抛出未捕获的异常会触发全局错误边界;用 try/catch 并返回结构化错误对象,可以让前端更优雅地显示错误信息。即便当前调用方不需要返回值,返回统一的状态对象便于未来扩展与调试。若需要重定向,可使用 next/navigation 的 redirect(这会抛出特定控制流),但仍应对其他分支返回值或错误信息。