🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

@complex-suite/request

Package Overview
Dependencies
Maintainers
1
Versions
16
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@complex-suite/request

a complex request

latest
Source
npmnpm
Version
2.0.15
Version published
Maintainers
1
Created
Source

Complex Request

这是一个功能强大且高度可扩展的 TypeScript 请求库,旨在通过分层、可组合的规则引擎,优雅地处理复杂的 Web 请求场景。

核心特性

  • 分层架构:
    • BaseRequest: 抽象请求基类,负责驱动整个请求生命周期,包括 Token 处理、请求重试、错误捕获等。
    • Rule: 可定制的规则引擎,将所有与具体业务相关的逻辑(如响应解析、登录/刷新流程)集中管理。
    • Token: 封装单个 Token 的所有行为,包括值的获取、存储、附加到请求和生命周期管理。
  • 强大的 Token 管理:
    • 支持多个具名 Token 和一个 refreshToken
    • 支持从内存、localStoragesessionStorage 中自动获取和缓存 Token。
    • 可配置 Token 的有效期、存储位置(header, body, params)和附加键名。
    • 自动化的登录和刷新流程,当 Token 失效时,可自动触发 loginrefresh 操作,并无缝地重试原始请求。
  • 高度可定制:
    • 响应解析: 可通过 parse 函数,将任何格式的服务器响应,适配为统一的 { status, data, ... } 格式。
    • 请求格式化: 可通过 format 函数,在请求发送前,对请求参数进行最后一次修改。
    • 底层实现无关: BaseRequest 是一个抽象类,您可以继承它,并使用任何底层的请求库(如 axios, fetch)来实现 $request 方法。
  • 数据格式转换:
    • 支持在 jsonform-data 之间自动转换请求数据。

安装

npm install @complex-suite/request

快速开始

下面是一个使用 fetch 作为底层实现的简单示例:

import { BaseRequest, Rule, Token } from '@complex-suite/request';

// 1. 创建一个继承自 BaseRequest 的具体请求类
//    我们在这里为泛型 R (原始响应) 和 L (本地配置) 提供了具体的类型
class MyRequest extends BaseRequest<any, { signal?: AbortSignal }> {
  $request(requestConfig) {
    // 使用 fetch 实现底层的请求逻辑
    const { url, method, headers, data, params, local } = requestConfig;
    const finalUrl = new URL(url);
    Object.keys(params).forEach(key => finalUrl.searchParams.append(key, params[key]));

    return fetch(finalUrl.toString(), {
      method,
      headers,
      body: data,
      signal: local?.signal // 传递 AbortSignal 以便取消请求
    }).then(res => res.json());
  }

  $parseError(error) {
    // 解析 fetch 抛出的错误
    return { type: 'internal', msg: error.message, data: error };
  }
}

// 2. 定义一套规则
const myRule = new Rule({
  prop: 'api',
  token: {
    data: {
      // 定义一个名为 'accessToken' 的 Token
      accessToken: {
        location: 'header', // 存储在 Header 中
        require: true // 这是一个必需的 Token
      }
    }
  },
  parse: (response) => {
    // 解析服务器响应
    if (response.code === 200) {
      return { status: 'success', data: response.data };
    } else if (response.code === 401) {
      return { status: 'login', data: null, msg: '请先登录' };
    } else {
      return { status: 'fail', data: null, msg: response.message };
    }
  },
  login: () => {
    // 定义登录逻辑
    return new Promise(resolve => {
      // ... 执行登录操作,例如弹出一个登录框
      // ... 登录成功后,使用 setToken 设置新的 Token
      myRequest.setToken('accessToken', 'new-token-from-server');
      resolve();
    });
  }
});

// 3. 实例化请求对象
const myRequest = new MyRequest({
  baseUrl: 'https://api.example.com',
  rule: myRule
});

// 4. 发送请求
// 4. 发送请求,并传递一个本地配置
const controller = new AbortController();
myRequest.get({
  url: '/user/profile',
  local: { signal: controller.signal } 
})
  .then(response => {
    console.log('用户信息:', response.data);
  })
  .catch(error => {
    console.error('请求失败:', error);
  });

// 可以在需要时取消请求
// controller.abort();

高级用法:泛型类型

@complex-suite/request 大量使用泛型来提供强大的类型安全。理解 RL 这两个核心泛型,能帮助您更好地利用这个库。

R - 原始响应 (Raw Response)

R 代表的是底层请求工具(如 fetch, axios)直接返回的、未经 rule.parse 解析的原始响应数据的类型。

Ruleparse 函数中,response 参数的类型就是 R

// 假设服务器返回的数据结构是 { code: number, data: T, message: string }
type ServerResponse<T> = {
  code: number;
  data: T;
  message: string;
}

// 在定义 Rule 时,我们可以将 R 指定为 ServerResponse<any>
const myRule = new Rule<ServerResponse<any>>({
  // ...
  parse: (response) => { // 在这里,`response` 的类型就是 ServerResponse<any>
    if (response.code === 200) {
      return { status: 'success', data: response.data };
    }
    // ...
  }
});

L - 本地配置 (Local Config)

L 代表的是一个可选的、用于传递给底层请求工具的、特定于实现的配置对象的类型。

这非常有用,因为不同的底层请求库(fetch, axios)有它们自己独特的配置选项(例如,axioscancelTokenfetchsignal)。L 允许您以类型安全的方式,将这些特定于实现的配置,一路传递到您自己实现的 $request 方法中。

在上面的“快速开始”示例中,我们通过 L 泛型,为 fetch 实现了一个请求取消的功能。

parse 函数:请求的“交通警察”

parse 函数是 @complex-suite/request 库的核心。它就像一个交通警察,负责检查每一个从服务器返回的原始响应 (R),并根据您定义的业务逻辑,告诉 BaseRequest 下一步应该做什么。

parse 函数必须返回一个 responseType 对象,其 status 字段决定了整个请求的走向:

interface responseType<D = any> {
  status: 'success' | 'fail' | 'login' | 'refresh'
  data: D
  code?: number | string
  msg?: string
}

下面是 BaseRequest 对每种 status 的处理方式:

  • 'success': 请求成功

    • 含义: 服务器成功处理了请求,且响应数据是有效的。
    • BaseRequest 的行为: request 方法返回的 Promise 将被 resolve,并将 data 字段作为结果传递下去。
  • 'fail': 请求失败

    • 含义: 服务器返回了一个业务逻辑上的错误(例如,表单验证失败、权限不足等)。
    • BaseRequest 的行为: request 方法返回的 Promise 将被 reject,并将整个 responseType 对象作为错误信息传递下去。
  • 'login': 需要登录

    • 含义: 用户的会话已完全失效,必须重新登录。
    • BaseRequest 的行为:
      • 自动触发您在 Rule 中定义的 login 函数。
      • login 函数成功执行后(即其返回的 Promise 被 resolve),BaseRequest自动重新发送之前失败的那个请求。
      • 整个过程对最终的调用者是完全透明的
  • 'refresh': 需要刷新 Token

    • 含义: 用户的访问令牌(Access Token)已过期,但刷新令牌(Refresh Token)仍然有效。
    • BaseRequest 的行为:
      • 自动触发您在 Rule 中定义的 refresh 函数。
      • refresh 函数成功执行后,BaseRequest自动重新发送之前失败的那个请求。
      • 如果 refresh 本身也失败了,或者刷新后重试的请求依然返回 'refresh'BaseRequest 会自动将流程降级为 'login'

通过精心设计您的 parse 函数,您可以以一种非常优雅和集中的方式,实现极其复杂的认证和重试逻辑。

依赖

  • @complex-suite/utils: 提供核心的工具函数和基类。
  • @complex-suite/plugin: 提供 notice 通知插件。

Keywords

complex

FAQs

Package last updated on 10 Jul 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts