本文介绍了TRPC入门的相关内容,涵盖了TRPC的基本概念、核心特性和环境搭建,帮助开发者快速上手TRPC。文章详细讲解了从环境搭建到创建第一个TRPC服务的步骤,并提供了实战案例和常见问题解决方法。
TRPC(TanRPC)是一个基于Node.js和TypeScript的高性能RPC框架,它提供了一种轻量且易于使用的RPC服务开发和调用方式。TRPC主要用于构建微服务架构中的服务间通信,可以大大简化服务间交互的复杂性,提高开发效率和系统灵活性。
TRPC的核心特性包括:
为了搭建TRPC开发环境,需要满足以下前提条件:
npm install -g typescript
确保以上环境已准备好后,可以进行下一步操作。
安装TRPC的依赖库需要确保Node.js和npm已经正确配置。以下是安装过程:
mkdir trpc-project cd trpc-project npm init
npm install @trpc/server @trpc/client @trpc/react-query @trpc/compat @tanstack/react-query
@trpc/server
:用于定义和实现服务器端的逻辑。@trpc/client
:用于定义和实现客户端的逻辑。@trpc/react-query
:用于在React应用中使用TRPC。@trpc/compat
:提供了一些兼容性和辅助功能。@tanstack/react-query
:用于在React应用中高效管理数据。定义路由:
使用@trpc/server
来定义服务端的路由和处理逻辑。首先,我们需要创建一个新的TypeScript文件,例如server.ts
。
import { createRouter } from '@trpc/server'; import { t } from './trpc'; const appRouter = createRouter().query('hello', { input: t.inputType, output: t.outputType, resolve: ({ input }) => { return `Hello, ${input.name}!`; }, }); export type AppRouter = typeof appRouter;
启动HTTP服务:
使用http
或express
等中间件来启动HTTP服务,监听指定端口。
import express from 'express'; import { createTRPCHandle } from '@trpc/server'; import { appRouter } from './server'; import { type } from './trpc'; const app = express(); const port = 3000; const trpc = createTRPCHandle({ router: appRouter, createContext }); app.use('/trpc', trpc.createExpressMiddleware()); app.listen(port, () => { console.log(`Server running on port ${port}`); }); function createContext() { return {}; }
npm run start
命令启动服务。
npm run start
npm install @trpc/client
设置客户端配置:
在客户端代码中设置HTTP客户端和TRPC客户端。
import { createTRPCClient } from '@trpc/client'; import { httpBatchLink } from '@trpc/client/links'; import superjson from 'superjson'; const trpcClient = createTRPCClient({ links: [ httpBatchLink({ url: 'http://localhost:3000/trpc', }), ], transformer: superjson, });
const response = await trpcClient.query.hello.query({ input: { name: 'World' } }); console.log(response);
TRPC遵循标准的请求-响应模型,客户端发出请求,服务端处理请求并返回响应。请求和响应是通过定义在服务端的路由来实现的。
定义请求示例:
import { createRouter } from '@trpc/server'; import { t } from './trpc'; const appRouter = createRouter().query('hello', { input: t.inputType, output: t.outputType, resolve: ({ input }) => { return `Hello, ${input.name}!`; }, });
TRPC支持中间件机制,中间件可以在请求的处理过程中插入自定义逻辑,如日志记录、错误处理、身份验证等。
next
函数作为参数,用于调用下一个中间件或结束请求处理。createRouter
中定义多个中间件,并在请求处理之前或之后执行。定义中间件示例:
import { createRouter } from '@trpc/server'; const appRouter = createRouter() .middleware((opts) => { console.log(`Request received for: ${opts.input.name}`); }) .query('hello', { input: t.inputType, output: t.outputType, resolve: ({ input }) => { return `Hello, ${input.name}!`; }, });
用户管理系统的基本功能包括用户注册、用户登录、用户信息查询和用户信息更新。具体需求如下:
首先,创建服务端代码,定义用户服务的路由和处理逻辑。
定义用户服务:
import { createRouter } from '@trpc/server'; import { t } from './trpc'; const appRouter = createRouter() .mutation('registerUser', { input: t.registerUserInput, output: t.registerUserOutput, resolve: ({ input }) => { // 模拟数据库操作 const users = [ { id: 1, username: 'alice', email: 'alice@example.com', password: '123456' }, ]; const user = { id: users.length + 1, username: input.username, email: input.email, password: input.password }; users.push(user); return user; }, }) .query('getUser', { input: t.getUserInput, output: t.getUserOutput, resolve: ({ input }) => { // 模拟数据库操作 const users = [ { id: 1, username: 'alice', email: 'alice@example.com', password: '123456' }, ]; return users.find(user => user.id === input.id); }, }) .mutation('updateUser', { input: t.updateUserInput, output: t.updateUserOutput, resolve: ({ input }) => { // 模拟数据库操作 let users = [ { id: 1, username: 'alice', email: 'alice@example.com', password: '123456' }, ]; const user = users.find(user => user.id === input.id); if (user) { user.email = input.email; user.password = input.password; } return user; }, });
启动HTTP服务:
import express from 'express'; import { createTRPCHandle } from '@trpc/server'; import { appRouter } from './server'; import { type } from './trpc'; const app = express(); const port = 3000; const trpc = createTRPCHandle({ router: appRouter, createContext }); app.use('/trpc', trpc.createExpressMiddleware()); app.listen(port, () => { console.log(`Server running on port ${port}`); }); function createContext() { return {}; }
客户端代码:
import { createTRPCClient } from '@trpc/client'; import { httpBatchLink } from '@trpc/client/links'; import superjson from 'superjson'; const trpcClient = createTRPCClient({ links: [ httpBatchLink({ url: 'http://localhost:3000/trpc', }), ], transformer: superjson, }); async function registerUser() { const response = await trpcClient.mutation.registerUser.mutate({ input: { username: 'bob', email: 'bob@example.com', password: '123456' }, }); console.log(response); } async function getUser() { const response = await trpcClient.query.getUser.query({ input: { id: 1 } }); console.log(response); } async function updateUser() { const response = await trpcClient.mutation.updateUser.mutate({ input: { id: 1, email: 'alice_new@example.com', password: 'newpassword' }, }); console.log(response); } registerUser(); getUser(); updateUser();
通过以上步骤,用户管理系统的基本功能已经实现,并可以通过TRPC服务端和客户端进行调用。
在使用TRPC的过程中,可能会遇到一些常见的错误,以下是一些常见问题及其解决方法:
未定义的类型错误:
// 错误示例 import { createRouter } from '@trpc/server'; import { t } from './trpc'; const appRouter = createRouter().query('hello', { input: t.inputType, output: t.outputType, resolve: ({ input }) => { return `Hello, ${input.name}!`; }, });
解决方法:
import { createRouter } from '@trpc/server'; import { t } from './trpc'; const appRouter = createRouter().query('hello', { input: t.inputType, output: t.outputType, resolve: ({ input }) => { return `Hello, ${input.name}!`; }, }); export type AppRouter = typeof appRouter;
客户端调用错误:
// 错误示例 import { createTRPCClient } from '@trpc/client'; import { httpBatchLink } from '@trpc/client/links'; import superjson from 'superjson'; const trpcClient = createTRPCClient({ links: [ httpBatchLink({ url: 'http://localhost:3000/trpc', }), ], transformer: superjson, }); async function registerUser() { const response = await trpcClient.mutation.registerUser.mutate({ input: { username: 'bob', email: 'bob@example.com', password: '123456' }, }); console.log(response); }
解决方法:
import { createTRPCClient } from '@trpc/client'; import { httpBatchLink } from '@trpc/client/links'; import superjson from 'superjson'; const trpcClient = createTRPCClient({ links: [ httpBatchLink({ url: 'http://localhost:3000/trpc', }), ], transformer: superjson, }); async function registerUser() { const response = await trpcClient.mutation.registerUser.mutate({ input: { username: 'bob', email: 'bob@example.com', password: '123456' }, }); console.log(response); } registerUser();
使用缓存:
在高并发环境中,可以通过缓存机制减少重复计算,提高性能。
const cache = new Map<number, any>(); const appRouter = createRouter() .query('getUser', { input: t.getUserInput, output: t.getUserOutput, resolve: ({ input }) => { if (!cache.has(input.id)) { const user = // 获取用户数据 cache.set(input.id, user); } return cache.get(input.id); }, });
异步处理:
使用异步处理方法可以避免阻塞线程,提高并发处理能力。
const appRouter = createRouter() .query('getUser', { input: t.getUserInput, output: t.getUserOutput, resolve: async ({ input }) => { const user = await getUserFromDatabase(input.id); return user; }, });
const appRouter = createRouter() .query('getUsers', { output: t.getUsersOutput, resolve: async () => { const users = await getUsersFromDatabase(); return users; }, });