跳至主要内容
版本:11.x

链接概述

链接使您能够自定义 tRPC 客户端和服务器之间数据流。链接应该只做一件事,这可以是对 tRPC 操作(查询、变异或订阅)的独立修改,也可以是基于操作的副作用(例如日志记录)。

您可以将链接组合成一个数组,并通过 links 属性提供给 tRPC 客户端配置,该属性表示链接链。这意味着 tRPC 客户端将在执行请求时按添加到 links 数组的顺序执行链接,并在处理响应时反向执行它们。以下是链接链的视觉表示

tRPC 链接图tRPC 链接图。基于 Apollo 的。
注意

以下示例假设您使用 Next.js,但如果您使用原生 tRPC 客户端,则可以添加与以下相同的示例

utils/trpc.ts
tsx
import { httpBatchLink, loggerLink } from '@trpc/client';
import { createTRPCNext } from '@trpc/next';
export default createTRPCNext<AppRouter>({
config() {
const url = `http://localhost:3000`;
return {
links: [
loggerLink(),
httpBatchLink({
url,
}),
],
};
},
});
utils/trpc.ts
tsx
import { httpBatchLink, loggerLink } from '@trpc/client';
import { createTRPCNext } from '@trpc/next';
export default createTRPCNext<AppRouter>({
config() {
const url = `http://localhost:3000`;
return {
links: [
loggerLink(),
httpBatchLink({
url,
}),
],
};
},
});

链接是一个遵循 TRPCLink 类型的函数。每个链接都由三个部分组成

  1. 链接返回一个函数,该函数具有一个带有 TRPCClientRuntime 类型的参数。此参数由 tRPC 传递,并在创建 终止链接 时使用。如果您没有创建终止链接,则可以只创建一个没有参数的函数。在这种情况下,链接应添加到 links 数组中而不调用(links: [..., myLink, httpBatchLink(...)])。
  2. 步骤 1 中的函数返回另一个函数,该函数接收一个具有两个属性的对象:op 是客户端正在执行的 Operationnext 是我们用来调用链中下一个链接的函数。
  3. 步骤 2 中的函数返回一个最终函数,该函数返回 @trpc/server 提供的 observable 函数。observable 接受一个函数,该函数接收一个 observer,它帮助我们的链接通知链中下一个链接如何处理操作结果。在这个函数中,我们可以只返回 next(op) 并保持原样,或者我们可以订阅 next,这使我们的链接能够处理操作结果。

示例

utils/customLink.ts
tsx
import { TRPCLink } from '@trpc/client';
import { observable } from '@trpc/server/observable';
import type { AppRouter } from 'server/routers/_app';
export const customLink: TRPCLink<AppRouter> = () => {
// here we just got initialized in the app - this happens once per app
// useful for storing cache for instance
return ({ next, op }) => {
// this is when passing the result to the next link
// each link needs to return an observable which propagates results
return observable((observer) => {
console.log('performing operation:', op);
const unsubscribe = next(op).subscribe({
next(value) {
console.log('we received value', value);
observer.next(value);
},
error(err) {
console.log('we received error', err);
observer.error(err);
},
complete() {
observer.complete();
},
});
return unsubscribe;
});
};
};
utils/customLink.ts
tsx
import { TRPCLink } from '@trpc/client';
import { observable } from '@trpc/server/observable';
import type { AppRouter } from 'server/routers/_app';
export const customLink: TRPCLink<AppRouter> = () => {
// here we just got initialized in the app - this happens once per app
// useful for storing cache for instance
return ({ next, op }) => {
// this is when passing the result to the next link
// each link needs to return an observable which propagates results
return observable((observer) => {
console.log('performing operation:', op);
const unsubscribe = next(op).subscribe({
next(value) {
console.log('we received value', value);
observer.next(value);
},
error(err) {
console.log('we received error', err);
observer.error(err);
},
complete() {
observer.complete();
},
});
return unsubscribe;
});
};
};

参考

如果您需要创建自定义链接的更真实的参考,您可以查看 tRPC 在 GitHub 上提供的一些内置链接。

终止链接 是链接链中的最后一个链接。终止链接不调用 next 函数,而是负责将您组合的 tRPC 操作发送到 tRPC 服务器并返回 OperationResultEnvelope

您添加到 tRPC 客户端配置的 links 数组至少应包含一个链接,并且该链接应为终止链接。如果 links 在末尾没有终止链接,则 tRPC 操作将不会发送到 tRPC 服务器。

httpBatchLink 是 tRPC 推荐的终止链接。

httpLinkwsLink 是终止链接的其他示例。

管理上下文

当操作沿着您的链接链移动时,它会维护一个上下文,每个链接都可以读取和修改该上下文。这允许链接沿着链传递元数据,其他链接在执行逻辑中使用这些元数据。

通过访问 op.context 获取当前上下文对象并修改它。

您可以通过向 queryuseQuery 钩子(或 mutationsubscription 等)提供上下文参数来设置特定操作的上下文对象的初始值。

有关示例用例,请参阅 为某些请求禁用批处理