链接与请求批处理
非官方测试版翻译
本页面由 PageTurner AI 翻译(测试版)。未经项目官方认可。 发现错误? 报告问题 →
类似于 urql 的 exchanges 或 Apollo 的 links。Links 机制允许您自定义 tRPC 客户端与 tRPC 服务端之间的数据流。
请求批处理
请求批处理功能默认启用,它会将多个请求合并发送至服务端。这意味着下面的代码只会产生 一次 HTTP 请求,在服务端也只会执行 一次 数据库查询:
ts// below will be done in the same request when batching is enabledconst somePosts = await Promise.all([client.query('post.byId', 1),client.query('post.byId', 2),client.query('post.byId', 3),]);
ts// below will be done in the same request when batching is enabledconst somePosts = await Promise.all([client.query('post.byId', 1),client.query('post.byId', 2),client.query('post.byId', 3),]);
自定义数据流
以下示例假设您使用 Next.js,但在原生 tRPC 客户端中同样适用
设置最大批处理量
此设置限制批量发送的请求数量(可有效防止 URL 过长导致触发 HTTP 413 错误)。
server.tsts// 👇 import the httpBatchLinkimport { httpBatchLink } from '@trpc/client/links/httpBatchLink';import { withTRPC } from '@trpc/next';import { AppType } from 'next/dist/shared/lib/utils';import type { AppRouter } from 'pages/api/trpc/[trpc]';const MyApp: AppType = ({ Component, pageProps }) => {return <Component {...pageProps} />;};export default withTRPC<AppRouter>({config() {return {links: [httpBatchLink({url: '/api/trpc',maxBatchSize: 10, // a reasonable size}),],};},})(MyApp);
server.tsts// 👇 import the httpBatchLinkimport { httpBatchLink } from '@trpc/client/links/httpBatchLink';import { withTRPC } from '@trpc/next';import { AppType } from 'next/dist/shared/lib/utils';import type { AppRouter } from 'pages/api/trpc/[trpc]';const MyApp: AppType = ({ Component, pageProps }) => {return <Component {...pageProps} />;};export default withTRPC<AppRouter>({config() {return {links: [httpBatchLink({url: '/api/trpc',maxBatchSize: 10, // a reasonable size}),],};},})(MyApp);
禁用请求批处理
1. 在服务端禁用 batching:
在 [trpc].ts 文件中:
pages/api/trpc/[trpc].tstsexport default trpcNext.createNextApiHandler({// [...]// 👇 disable batchingbatching: {enabled: false,},});
pages/api/trpc/[trpc].tstsexport default trpcNext.createNextApiHandler({// [...]// 👇 disable batchingbatching: {enabled: false,},});
2. 在 tRPC 客户端使用无批处理链接
pages/_app.tsxtsx// 👇 import the httpLinkimport { httpLink } from '@trpc/client/links/httpLink';import { withTRPC } from '@trpc/next';import { AppType } from 'next/dist/shared/lib/utils';import type { AppRouter } from 'pages/api/trpc/[trpc]';const MyApp: AppType = ({ Component, pageProps }) => {return <Component {...pageProps} />;};export default withTRPC<AppRouter>({config() {return {links: [httpLink({url: '/api/trpc',}),],};},// ssr: false,})(MyApp);
pages/_app.tsxtsx// 👇 import the httpLinkimport { httpLink } from '@trpc/client/links/httpLink';import { withTRPC } from '@trpc/next';import { AppType } from 'next/dist/shared/lib/utils';import type { AppRouter } from 'pages/api/trpc/[trpc]';const MyApp: AppType = ({ Component, pageProps }) => {return <Component {...pageProps} />;};export default withTRPC<AppRouter>({config() {return {links: [httpLink({url: '/api/trpc',}),],};},// ssr: false,})(MyApp);
使用 splitLink 控制请求流
为特定请求禁用批处理
1. 配置客户端 / _app.tsx
pages/_app.tsxtsximport { httpBatchLink } from '@trpc/client/links/httpBatchLink';import { httpLink } from '@trpc/client/links/httpLink';import { splitLink } from '@trpc/client/links/splitLink';import { withTRPC } from '@trpc/next';// [..]export default withTRPC<AppRouter>({config() {const url = `http://localhost:3000`;return {links: [splitLink({condition(op) {// check for context property `skipBatch`return op.context.skipBatch === true;},// when condition is true, use normal requesttrue: httpLink({url,}),// when condition is false, use batchingfalse: httpBatchLink({url,}),}),],};},})(MyApp);
pages/_app.tsxtsximport { httpBatchLink } from '@trpc/client/links/httpBatchLink';import { httpLink } from '@trpc/client/links/httpLink';import { splitLink } from '@trpc/client/links/splitLink';import { withTRPC } from '@trpc/next';// [..]export default withTRPC<AppRouter>({config() {const url = `http://localhost:3000`;return {links: [splitLink({condition(op) {// check for context property `skipBatch`return op.context.skipBatch === true;},// when condition is true, use normal requesttrue: httpLink({url,}),// when condition is false, use batchingfalse: httpBatchLink({url,}),}),],};},})(MyApp);
2. 执行无批处理请求
MyComponent.tsxtsxexport function MyComponent() {const postsQuery = trpc.useQuery(['posts'], {context: {skipBatch: true,},});return (<pre>{JSON.stringify(postsQuery.data ?? null, null, 4)}</pre>)})
MyComponent.tsxtsxexport function MyComponent() {const postsQuery = trpc.useQuery(['posts'], {context: {skipBatch: true,},});return (<pre>{JSON.stringify(postsQuery.data ?? null, null, 4)}</pre>)})
或:
client.tstsconst postResult = client.query('posts', null, {context: {skipBatch: true,},});
client.tstsconst postResult = client.query('posts', null, {context: {skipBatch: true,},});
创建自定义链接
pages/_app.tsxtsximport { TRPCLink } from '@trpc/client';import type { AppRouter } from 'pages/api/trpc/[trpc]';const customLink: TRPCLink<AppRouter> = (runtime) => {// here we just got initialized in the app - this happens once per app// useful for storing cache for instancereturn ({ prev, next, op }) => {// this is when passing the result to the next linknext(op, (result) => {// this is when we've gotten result from the serverif (result instanceof Error) {// maybe send to bugsnag?}prev(result);});};};export default withTRPC<AppRouter>({config() {return {links: [customLink,// [..]// ❗ Make sure to end with a `httpBatchLink` or `httpLink`],};},// ssr: false})(MyApp);
pages/_app.tsxtsximport { TRPCLink } from '@trpc/client';import type { AppRouter } from 'pages/api/trpc/[trpc]';const customLink: TRPCLink<AppRouter> = (runtime) => {// here we just got initialized in the app - this happens once per app// useful for storing cache for instancereturn ({ prev, next, op }) => {// this is when passing the result to the next linknext(op, (result) => {// this is when we've gotten result from the serverif (result instanceof Error) {// maybe send to bugsnag?}prev(result);});};};export default withTRPC<AppRouter>({config() {return {links: [customLink,// [..]// ❗ Make sure to end with a `httpBatchLink` or `httpLink`],};},// ssr: false})(MyApp);