跳至主内容
版本:10.x

定义过程

非官方测试版翻译

本页面由 PageTurner AI 翻译(测试版)。未经项目官方认可。 发现错误? 报告问题 →

过程(Procedure)是暴露给客户端的函数,它可以是以下类型之一:

  • Query(查询)- 用于获取数据,通常不会更改任何数据

  • Mutation(变更)- 用于发送数据,常用于创建/更新/删除操作

  • Subscription(订阅)- 您可能不需要此功能,我们提供了专门文档

tRPC 中的过程是创建后端函数的灵活原语。它们采用不可变的构建器模式,这意味着您可以创建可重用的基础过程,在多个过程间共享功能。

编写过程

在 tRPC 初始化时创建的 t 对象会返回初始的 t.procedure,所有其他过程都基于此构建:

ts
import { initTRPC } from '@trpc/server';
import { z } from 'zod';
 
const t = initTRPC.context<{ signGuestBook: () => Promise<void> }>().create();
 
export const router = t.router;
export const publicProcedure = t.procedure;
 
const appRouter = router({
// Queries are the best place to fetch data
hello: publicProcedure.query(() => {
return {
message: 'hello world',
};
}),
 
// Mutations are the best place to do things like updating a database
goodbye: publicProcedure.mutation(async (opts) => {
await opts.ctx.signGuestBook();
 
return {
message: 'goodbye!',
};
}),
});
ts
import { initTRPC } from '@trpc/server';
import { z } from 'zod';
 
const t = initTRPC.context<{ signGuestBook: () => Promise<void> }>().create();
 
export const router = t.router;
export const publicProcedure = t.procedure;
 
const appRouter = router({
// Queries are the best place to fetch data
hello: publicProcedure.query(() => {
return {
message: 'hello world',
};
}),
 
// Mutations are the best place to do things like updating a database
goodbye: publicProcedure.mutation(async (opts) => {
await opts.ctx.signGuestBook();
 
return {
message: 'goodbye!',
};
}),
});

可重用的"基础过程"

作为通用模式,我们建议将 t.procedure 重命名并导出为 publicProcedure,这样您就可以为特定用例创建其他命名过程并同样导出。这种模式称为"基础过程",是 tRPC 中实现代码和行为复用的关键模式;每个应用都可能需要它。

以下示例接收用户输入并像警惕的镇民一样对其进行授权。显然这是个简化的人为示例,并非安全的用户授权方式。实际应用中,您可能需要组合使用请求头上下文中间件元数据来实现用户认证和授权。

ts
export const authorizedProcedure = publicProcedure
.input(z.object({ townName: z.string() }))
.use((opts) => {
if (opts.input.townName !== 'Pucklechurch') {
throw new TRPCError({
code: 'FORBIDDEN',
message: "We don't take kindly to out-of-town folk",
});
}
 
return opts.next();
});
 
export const appRouter = t.router({
hello: authorizedProcedure.query(() => {
return {
message: 'hello world',
};
}),
goodbye: authorizedProcedure.mutation(async (opts) => {
await opts.ctx.signGuestBook();
 
return {
message: 'goodbye!',
};
}),
});
ts
export const authorizedProcedure = publicProcedure
.input(z.object({ townName: z.string() }))
.use((opts) => {
if (opts.input.townName !== 'Pucklechurch') {
throw new TRPCError({
code: 'FORBIDDEN',
message: "We don't take kindly to out-of-town folk",
});
}
 
return opts.next();
});
 
export const appRouter = t.router({
hello: authorizedProcedure.query(() => {
return {
message: 'hello world',
};
}),
goodbye: authorizedProcedure.mutation(async (opts) => {
await opts.ctx.signGuestBook();
 
return {
message: 'goodbye!',
};
}),
});