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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@tanggoat/request

v2.1.7

Published

A TypeScript HTTP request library based on Axios

Readme

@tanggoat/request

一个基于 Axios 的 TypeScript HTTP 请求库,提供强大的拦截器、自动重试、请求去重与取消能力,且对类型推断友好。

✨ 特性

  • 🚀 基于 Axios,稳定可靠
  • 🔧 完整 TypeScript 类型定义
  • 🧱 拦截器链:全局 + 实例 + 单请求三级拦截
  • ♻️ 自动重试:支持重试次数/延迟/自定义条件,或一键开启默认策略
  • 🚫 请求去重:在窗口期内自动取消重复请求
  • ⛔️ 请求取消:支持按 URL 取消与批量取消
  • 📦 多格式输出:CJS + ESM + d.ts

📦 安装

# npm
npm install @tanggoat/request
# yarn
yarn add @tanggoat/request
# pnpm
pnpm add @tanggoat/request

🚀 快速开始

import Request from '@tanggoat/request';

const request = new Request({
  baseURL: 'https://api.example.com',
  timeout: 10000
});

// 基础请求
type User = { id: string; name: string };
request.request<User>({ url: '/users/1', method: 'GET' }).then(console.log);

🧱 拦截器

拦截器执行顺序(请求发起到响应返回):

  • 接口请求 → 实例请求 → 全局请求 → 实例响应 → 全局响应 → 接口响应
const request = new Request({
  baseURL: 'https://api.example.com',
  interceptors: {
    requestInterceptors: (config) => {
      // 实例级请求拦截
      return config;
    },
    responseInterceptors: (response) => {
      // 实例级响应拦截(在全局响应拦截之后)
      return response;
    },
  }
});

// 单请求拦截器
request.request({
  url: '/users',
  method: 'GET',
  interceptors: {
    requestInterceptors: (cfg) => ({ ...cfg }),
    responseInterceptors: (res) => res,
  }
});

♻️ 自动重试(retryConfig)

为单个请求开启自动重试:

// 方式一:使用默认策略(等价于 { retryCount: 2, retryDelay: 1000 })
request.request({ url: '/unstable', method: 'GET', retryConfig: true });

// 方式二:自定义策略
request.request({
  url: '/unstable',
  method: 'GET',
  retryConfig: {
    retryCount: 3,            // 重试次数(默认 2)
    retryDelay: 1500,         // 重试间隔毫秒(默认 1000)
    retryCondition: (error, attempt) => {
      // 返回 true 才会继续重试
      return !error.response || error.response.status >= 500;
    }
  }
});

默认重试条件(当未提供 retryCondition 时):

  • 不是手动取消(非 axios.isCancel)
  • 无响应(网络错误/超时)或 HTTP 5xx 或 429

库内默认值与默认条件由 ./util 提供:

  • DEFAULT_RETRY_COUNTDEFAULT_RETRY_DELAY
  • defaultRetryCondition(error, attempt)

🧯 请求去重(noRepeatRequest)

在指定时间窗口内取消重复请求(默认窗口 2000ms):

request.request({ url: '/list', method: 'GET', noRepeatRequest: true });

说明:同一 URL 在窗口期内仅允许第一条通过,其余自动取消(内部通过 AbortController 实现)。

⛔️ 取消请求

// 取消指定 URL
request.cancelRequest('/tasks');
// 批量取消
request.cancelRequest(['/a', '/b']);
// 取消全部
request.cancelAllRequest();

🧩 API 文档

类型

import type { CreateRequestConfig, RequestConfig, RequestInterceptors } from '@tanggoat/request';

// 重试配置
export type IRetryConfig = {
  retryCount?: number;                                 // 默认 2
  retryDelay?: number;                                 // 默认 1000ms
  retryCondition?: (error: any, attempt: number) => boolean; // 返回 true 则继续重试
}

// 请求配置(节选)
export interface RequestConfig<T = AxiosResponse> extends InternalAxiosRequestConfig {
  interceptors?: RequestInterceptors<T>;
  noRepeatRequest?: boolean;
  retryConfig?: IRetryConfig | boolean;                // true 表示启用默认重试策略
}

new Request(config: CreateRequestConfig)
  • 常用方法
    • request<T>(config: RequestConfig<T>): Promise<T>
    • cancelRequest(url: string | string[]): void
    • cancelAllRequest(): void

🧪 示例

1) 搭配实例拦截器与单请求拦截器

const request = new Request({
  baseURL: 'https://api.example.com',
  interceptors: {
    requestInterceptors: (cfg) => ({ ...cfg }),
    responseInterceptors: (res) => res,
  }
});

request.request({
  url: '/users',
  method: 'GET',
  interceptors: {
    requestInterceptors: (cfg) => ({ ...cfg, headers: { ...cfg.headers, 'X-Req': '1' } }),
    responseInterceptors: (res) => res,
  }
});

2) 自动重试

// 默认重试
request.request({ url: '/ping', method: 'GET', retryConfig: true });

// 自定义重试
request.request({
  url: '/ping',
  method: 'GET',
  retryConfig: { retryCount: 3, retryDelay: 2000 }
});

3) 请求去重 + 取消

request.request({ url: '/list', method: 'GET', noRepeatRequest: true });
// 稍后取消
request.cancelRequest('/list');

🏗️ 在 Monorepo 中实时联调

使用 pnpm workspace:

  • 根目录 pnpm-workspace.yaml
packages:
  - "packages/*"
  - "apps/*"
  • 在 app 里声明依赖(例如 demo 应用)
{
  "dependencies": {
    "@tanggoat/request": "workspace:*"
  }
}
  • 在 request 包内提供脚本(示例)
{
  "scripts": {
    "build": "rimraf dist && tsup src/index.ts --format cjs,esm --dts",
    "dev": "tsup src/index.ts --format cjs,esm --dts --watch --sourcemap",
    "clean": "rimraf dist"
  }
}
  • 同时启动两个终端:
    • request 包:pnpm --filter @tanggoat/request dev
    • demo 应用:pnpm --filter demo dev

当你修改 packages/request/src/** 时,tsup 会增量编译到 dist/,apps 会实时感知更新。

📦 发布(建议)

  • 入口与导出指向 dist 构建产物:
    • main: dist/index.cjs
    • module: dist/index.mjs
    • types: dist/index.d.ts
    • files: ["dist"]
  • 使用 prepublishOnly 自动构建:"prepublishOnly": "pnpm build"
  • 可引入 Changesets 管理版本(可选)

📝 许可证

MIT