tRPC 的 Links 特性详解及应用

举报
汪子熙 发表于 2025/10/11 14:19:18 2025/10/11
【摘要】 在现代 Web 应用开发中, tRPC(TypeScript Remote Procedure Call)是一种流行的框架,它允许开发者使用 TypeScript 定义并调用类型安全的 API。tRPC 的设计初衷是减少前后端代码重复并提供强大的类型推导能力,使开发者能够快速、可靠地构建全栈应用。与传统 REST API 或 GraphQL 不同,tRPC 利用 TypeScript 的类型...

在现代 Web 应用开发中, tRPC(TypeScript Remote Procedure Call)是一种流行的框架,它允许开发者使用 TypeScript 定义并调用类型安全的 API。tRPC 的设计初衷是减少前后端代码重复并提供强大的类型推导能力,使开发者能够快速、可靠地构建全栈应用。与传统 REST API 或 GraphQL 不同,tRPC 利用 TypeScript 的类型推断功能,为客户端和服务器端之间的通信提供无缝的开发体验。

在 tRPC 的生态中,Links 是一项核心功能。它通过拦截和处理请求与响应链,为开发者提供高度灵活的扩展能力。

Links 的核心概念

Links 是 tRPC 中用于中间处理的机制。它类似于中间件,但专注于 API 请求的拦截、处理和转发。Links 让开发者可以以模块化的方式增强或改变请求和响应的行为,从而满足特定业务需求。

每个 Link 实际上是一个函数,它接收传入的请求,处理之后将其传递给下一个 Link 或直接返回响应结果。这种设计模式赋予 Links 极高的组合性和灵活性,使其可以被用于多种场景,例如:

  • 记录请求日志。
  • 添加或验证认证令牌。
  • 处理全局错误。
  • 实现请求重试策略。

类比:HTTP 中的中间件

Links 的工作机制与 HTTP 中的中间件非常类似。想象一个快递分发中心,包裹需要经过多个站点,每个站点都可以对包裹进行处理。例如,一个站点可能负责检查包裹是否损坏,另一个站点可能负责分类投递,最后的站点则完成派送。tRPC 的 Links 就是这种"站点"的抽象,它们共同形成一个数据处理链条。

Links 的实现方式

基础结构

一个 Link 是一个接受请求上下文(Context)并返回处理结果的函数。在 tRPC 中,Links 可以以链式形式组合在一起。以下是一个基础的 Links 实现:

import { TRPCLink } from '@trpc/client';

const exampleLink: TRPCLink = (runtime) => {
  return ({ op, next, onDestroy }) => {
    console.log(`Request initiated: ${op.type} -> ${op.path}`);

    return next(op).then((result) => {
      console.log(`Response received:`, result);
      return result;
    });
  };
};

上述代码定义了一个简单的 Link,它记录请求路径和响应结果。这种基础形式可以进一步扩展,形成复杂的处理逻辑。

示例:添加认证令牌

假设一个场景,客户端需要在每个请求头中附加 JWT(JSON Web Token)以进行用户身份验证。这可以通过 Links 实现:

import { TRPCLink } from '@trpc/client';

const authLink: TRPCLink = (runtime) => {
  return ({ op, next }) => {
    const token = localStorage.getItem('authToken');
    op.context.headers = {
      ...op.context.headers,
      Authorization: `Bearer ${token}`,
    };

    return next(op);
  };
};

此代码片段会自动将存储在本地的 JWT 附加到每个请求的头部,确保请求经过身份验证。

Links 的实际应用场景

日志记录

在复杂的分布式系统中,记录每个请求的详细信息对于调试和监控至关重要。例如,一个日志记录 Link 可以如下实现:

const loggerLink: TRPCLink = () => {
  return ({ op, next }) => {
    console.log(`[${new Date().toISOString()}] Starting request to ${op.path}`);

    return next(op).then((result) => {
      console.log(`[${new Date().toISOString()}] Received response for ${op.path}`);
      return result;
    });
  };
};

错误处理

当 API 返回错误时,Links 可以捕获并统一处理这些错误。例如:

const errorHandlerLink: TRPCLink = () => {
  return ({ op, next }) => {
    return next(op).catch((error) => {
      console.error(`Error in ${op.path}:`, error);
      throw error;
    });
  };
};

这个 Link 捕获了所有 API 错误并将其记录到控制台,同时将错误重新抛出,以便上层逻辑继续处理。

重试策略

某些情况下,例如网络抖动或服务端瞬时故障,请求可能失败。这时可以通过 Links 实现请求重试机制:

const retryLink: TRPCLink = () => {
  return ({ op, next }) => {
    const maxRetries = 3;
    let attempt = 0;

    const execute = () => {
      attempt++;
      return next(op).catch((error) => {
        if (attempt < maxRetries) {
          console.log(`Retrying ${op.path} (${attempt}/${maxRetries})`);
          return execute();
        }
        throw error;
      });
    };

    return execute();
  };
};

真实案例:电商应用中的应用

以电商系统为例,假设一个客户端需要从服务端拉取订单列表数据。对于每个请求:

  1. 首先需要在请求头中附加用户身份的认证令牌。
  2. 如果请求失败,需要最多重试两次。
  3. 所有请求和响应的数据都需要记录到日志。

通过 Links,可以将上述逻辑模块化并串联:

const links = [
  authLink,
  retryLink,
  loggerLink,
];

这个配置确保所有请求都经过认证、重试和日志记录的处理逻辑,形成一个清晰而可靠的处理链。

总结

tRPC 的 Links 功能通过模块化、可组合的方式,赋予开发者极大的灵活性和控制能力。在实际开发中,合理使用 Links 能显著提升代码的可维护性和扩展性。无论是记录日志、错误处理,还是实现复杂的请求逻辑,Links 都提供了强大的支持。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。