npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

complex-request

v1.1.1

Published

a complex request

Downloads

94

Readme

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-request

快速开始

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

import { BaseRequest, Rule, Token } from 'complex-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-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-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 的行为:
      1. 自动触发您在 Rule 中定义的 login 函数。
      2. login 函数成功执行后(即其返回的 Promise 被 resolve),BaseRequest自动重新发送之前失败的那个请求。
      3. 整个过程对最终的调用者是完全透明的
  • 'refresh': 需要刷新 Token

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

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

依赖