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

request-core-adapter

v1.0.1

Published

基于适配器模式的统一请求工具库

Readme

request-core

一个基于适配器模式的 HTTP 请求库,支持 umi-request 和 axios,提供统一的 API 接口和丰富的功能特性。

✨ 特性

  • 🔌 适配器模式:支持 umi-request 和 axios,可轻松扩展其他 HTTP 客户端
  • 🔐 自动认证:自动添加 Authorization 和 tenant-id 请求头
  • 🚫 重复请求取消:支持取消重复的请求,避免资源浪费
  • 📊 业务状态码处理:灵活处理业务状态码,支持自定义允许的状态码
  • 🎯 统一错误处理:统一的错误处理机制,支持自定义错误提示
  • 📝 请求日志:内置请求日志功能,方便调试
  • 🛡️ 类型安全:完整的 TypeScript 类型定义
  • 401 自动处理:自动处理未授权状态,触发回调

📦 安装

pnpm add request-core
# 或
npm install request-core
# 或
yarn add request-core

🚀 快速开始

基础用法

import { createRequest } from 'request-core';
import { message } from 'antd'; // 或其他 UI 库

const request = createRequest({
  baseUrl: 'https://api.example.com',
  adapterType: 'umi', // 或 'axios'
  getToken: () => localStorage.getItem('token'),
  getTenantId: () => localStorage.getItem('tenantId'),
  enableLog: true,
  onUnauthorized: () => {
    // 处理未授权
    window.location.href = '/login';
  },
  onErrorTip: (msg, error) => {
    // 统一错误提示
    message.error(msg);
  },
  onError: (error) => {
    // 错误处理回调
    console.error('Request error:', error);
  },
});

// 使用
const data = await request.get('/api/users');

使用 Axios 适配器

import axios from 'axios';
import { createRequest } from 'request-core';

const axiosInstance = axios.create({
  timeout: 10000,
});

const request = createRequest({
  adapterType: 'axios',
  axiosInstance,
  baseUrl: 'https://api.example.com',
  getToken: () => localStorage.getItem('token'),
});

📖 API 文档

createRequest(options)

创建请求实例。

参数

interface CreateOptions extends RequestGlobalConfig {
  adapterType?: 'umi' | 'axios';  // 适配器类型,默认为 'umi'
  axiosInstance?: AxiosInstance;   // 使用 axios 适配器时必需
}

返回值

返回一个包含以下方法的请求对象:

{
  get: <T>(url: string, params?: any, config?: RequestConfig) => Promise<ResponseData<T>>;
  post: <T>(url: string, data?: any, config?: RequestConfig) => Promise<ResponseData<T>>;
  put: <T>(url: string, data?: any, config?: RequestConfig) => Promise<ResponseData<T>>;
  delete: <T>(url: string, data?: any, config?: RequestConfig) => Promise<ResponseData<T>>;
}

请求方法

get<T>(url, params?, config?)

发送 GET 请求。

const users = await request.get<User[]>('/api/users', { page: 1, size: 10 });

post<T>(url, data?, config?)

发送 POST 请求。

const user = await request.post<User>('/api/users', {
  name: 'John',
  email: '[email protected]',
});

put<T>(url, data?, config?)

发送 PUT 请求。

const user = await request.put<User>('/api/users/1', {
  name: 'John Updated',
});

delete<T>(url, data?, config?)

发送 DELETE 请求。

await request.delete('/api/users/1');

⚙️ 配置选项

RequestGlobalConfig

全局配置选项:

| 选项 | 类型 | 说明 | 默认值 | |------|------|------|--------| | baseUrl | string | 基础 URL | - | | getToken | () => string \| null | 获取 token 的函数 | - | | getTenantId | () => string \| null | 获取租户 ID 的函数 | - | | onUnauthorized | () => void | 401 未授权回调 | - | | onErrorTip | (message: string, error: any) => void | 错误提示回调 | - | | onError | (error: any) => void | 错误处理回调 | - | | enableLog | boolean | 是否启用日志 | false |

RequestConfig

请求配置选项(可在每次请求时覆盖):

| 选项 | 类型 | 说明 | 默认值 | |------|------|------|--------| | showError | boolean | 是否显示错误提示 | true | | throwError | boolean | 是否抛出错误 | true | | errorMessage | string | 自定义错误消息 | - | | businessStatusCodes | number[] | 允许的业务状态码 | [409] | | cancelDuplicate | boolean | 是否取消重复请求 | false | | headers | Record<string, string> | 自定义请求头 | - | | signal | AbortSignal | 取消信号 | - |

📝 使用示例

基础请求

// GET 请求
const users = await request.get('/api/users');

// POST 请求
const newUser = await request.post('/api/users', {
  name: 'John',
  email: '[email protected]',
});

// PUT 请求
const updatedUser = await request.put('/api/users/1', {
  name: 'John Updated',
});

// DELETE 请求
await request.delete('/api/users/1');

带参数的请求

// GET 请求带查询参数
const users = await request.get('/api/users', {
  page: 1,
  size: 10,
  keyword: 'john',
});

// POST 请求带数据
const result = await request.post('/api/users', {
  name: 'John',
  email: '[email protected]',
});

自定义配置

// 不显示错误提示
const data = await request.get('/api/users', {}, {
  showError: false,
});

// 不抛出错误,返回错误响应
const result = await request.post('/api/users', userData, {
  throwError: false,
});

// 自定义错误消息
const result = await request.post('/api/users', userData, {
  errorMessage: '创建用户失败,请重试',
});

// 允许特定的业务状态码
const result = await request.post('/api/users', userData, {
  businessStatusCodes: [409, 422],
});

// 取消重复请求
const result = await request.get('/api/users', {}, {
  cancelDuplicate: true,
});

错误处理

try {
  const user = await request.get('/api/users/1');
} catch (error) {
  // 处理错误
  console.error('Request failed:', error);
}

// 或者不抛出错误
const result = await request.get('/api/users/1', {}, {
  throwError: false,
});

if (result.code !== 200) {
  console.error('Request failed:', result.message);
}

取消请求

const controller = new AbortController();

request.get('/api/users', {}, {
  signal: controller.signal,
});

// 取消请求
controller.abort();

🔌 适配器

Umi-Request 适配器

默认适配器,基于 umi-request。

const request = createRequest({
  adapterType: 'umi',
  baseUrl: 'https://api.example.com',
});

Axios 适配器

使用 axios 作为 HTTP 客户端。

import axios from 'axios';

const axiosInstance = axios.create({
  timeout: 10000,
});

const request = createRequest({
  adapterType: 'axios',
  axiosInstance,
  baseUrl: 'https://api.example.com',
});

自定义适配器

你可以实现 HttpAdapter 接口来创建自定义适配器:

import { HttpAdapter } from 'request-core';
import { RequestConfig, AdapterResponse } from 'request-core';

const myAdapter: HttpAdapter = {
  request: async (url: string, options: RequestConfig): Promise<AdapterResponse> => {
    // 实现你的请求逻辑
    const response = await fetch(url, {
      method: options.method,
      headers: options.headers,
      body: options.data ? JSON.stringify(options.data) : undefined,
    });
    
    return {
      data: await response.json(),
      status: response.status,
      headers: Object.fromEntries(response.headers.entries()),
    };
  },
};

📋 类型定义

ResponseData

interface ResponseData<T = any> {
  code: number;
  message: string;
  data: T;
  error?: any;
}

RequestConfig

interface RequestConfig extends Omit<RequestOptionsInit, 'data' | 'params'> {
  data?: any;
  params?: any;
  errorMessage?: string;
  showError?: boolean;
  throwError?: boolean;
  businessStatusCodes?: number[];
  enableLog?: boolean;
  cancelDuplicate?: boolean;
}

RequestGlobalConfig

interface RequestGlobalConfig {
  baseUrl?: string;
  getToken?: () => string | null;
  getTenantId?: () => string | null;
  onUnauthorized?: () => void;
  onErrorTip?: (message: string, error: any) => void;
  onError?: (error: any) => void;
  enableLog?: boolean;
}

interface AdapterResponse<T = any> {
  data: T;
  status: number;
  headers?: any;
}

interface HttpAdapter {
  request: (url: string, options: RequestConfig) => Promise<AdapterResponse>;
}

🎯 业务状态码处理

默认情况下,只有 code === 200code === 0 的响应会被视为成功。你可以通过 businessStatusCodes 配置允许其他状态码:

// 允许 409 和 422 状态码
const result = await request.post('/api/users', userData, {
  businessStatusCodes: [409, 422],
});

默认允许的状态码是 [409]

🚫 重复请求取消

启用 cancelDuplicate 选项后,相同的请求(相同的 method、url、params、data)会自动取消之前的请求:

const result = await request.get('/api/users', {}, {
  cancelDuplicate: true,
});

📝 日志

启用日志后,会在控制台输出请求信息:

const request = createRequest({
  enableLog: true,
  // ...
});

// 输出示例:
// 🚀 GET https://api.example.com/api/users
// ✅ GET https://api.example.com/api/users 234ms
// ❌ POST https://api.example.com/api/users 123ms Error: ...

🔐 认证

自动添加认证信息到请求头:

const request = createRequest({
  getToken: () => localStorage.getItem('token'),
  getTenantId: () => localStorage.getItem('tenantId'),
});

// 请求会自动添加:
// Authorization: Bearer <token>
// tenant-id: <tenantId>

⚠️ 错误处理

自动错误提示

通过 onErrorTip 回调统一处理错误提示:

import { message } from 'antd';

const request = createRequest({
  onErrorTip: (msg, error) => {
    message.error(msg);
  },
});

401 未授权处理

自动检测 401 状态码并触发回调:

const request = createRequest({
  onUnauthorized: () => {
    // 清除 token
    localStorage.removeItem('token');
    // 跳转到登录页
    window.location.href = '/login';
  },
});

取消请求处理

当请求被取消时(AbortError),会返回一个特殊的响应:

{
  code: -1,
  message: 'canceled',
  data: null
}

📄 License

ISC

🤝 贡献

欢迎提交 Issue 和 Pull Request!