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

@baseh/h-request

v1.0.0

Published

前端请求库封装

Readme

src/utils/request.ts:

import { inject, createFetchRequestor } from 'request-library';

// 创建请求器
const requestor = createFetchRequestor(import.meta.env.VITE_API_BASE_URL || '');

// 添加请求拦截器(添加 token)
requestor.on('beforeRequest', (config) => {
  const token = localStorage.getItem('token');
  if (token) {
    config.headers = {
      ...config.headers,
      'Authorization': `Bearer ${token}`
    };
  }
});

// 添加响应拦截器(处理错误)
requestor.on('error', (error, config) => {
  console.error('请求错误:', error);
  // 可以在这里处理统一错误,比如跳转到登录页
});

// 注入请求器
inject(requestor);

export default requestor;

在 main.ts 中引入:

import { createApp } from 'vue';
import App from './App.vue';
import './utils/request'; // 初始化请求库

createApp(App).mount('#app');

前端请求库

一个完整的前端请求库封装方案,提供请求缓存、请求幂等、请求并发、请求串行等高级功能。

📦 项目结构

request-library/
├── src/
│   ├── types/              # 类型定义
│   │   └── index.ts
│   ├── request-imp/        # 请求实现层(基于fetch)
│   │   └── fetch-imp.ts
│   ├── request-core/       # 请求核心层
│   │   ├── index.ts        # 缓存、幂等、并发、串行、重试
│   │   └── store.ts        # 缓存存储实现
│   ├── request-bus/        # 请求业务层
│   │   ├── index.ts
│   │   ├── templet/        # 样板代码(自动生成)
│   │   └── patch/          # 补丁代码(手动修改)
│   └── index.ts           # 主入口
├── examples/              # 使用示例
├── package.json
├── tsconfig.json
└── README.md

🏗️ 架构设计

采用三层架构设计,从下往上依次是:

  1. 请求实现层(request-imp)

    • 提供请求基本功能
    • 支持多种实现方式:fetch、XHR、axios
    • 通过依赖倒置原则与上层解耦
    • 可以灵活切换实现方式,无需修改业务代码
  2. 请求核心层(request-core)

    • 提供网络上层控制功能
    • 包括:请求缓存、请求幂等、请求并发、请求串行、请求重试
  3. 请求业务层(request-bus)

    • 封装业务接口
    • 接入公司内部协议规范
    • 向外提供业务接口 API

🚀 快速开始

安装

npm install
npm run build

基础使用

import { inject } from './src';
// 可以选择不同的实现方式
import { createFetchRequestor } from './src/request-imp/fetch-imp';
import { createXHRRequestor } from './src/request-imp/xhr-imp';
import { createAxiosRequestor } from './src/request-imp/axios-imp';

// 方式1:使用 Fetch(推荐,现代浏览器)
const requestor = createFetchRequestor('https://api.example.com');
inject(requestor);

// 方式2:使用 XHR(兼容性好)
// const requestor = createXHRRequestor('https://api.example.com');
// inject(requestor);

// 方式3:使用 Axios(功能丰富,需要安装 axios)
// const requestor = createAxiosRequestor('https://api.example.com');
// inject(requestor);

// 使用请求(无论使用哪种实现,API 完全一致)
const response = await requestor.get('/api/articles');
console.log(response.data);

业务接口使用

import { publishArticle, getArticles } from './src/request-bus';

// 发布文章(自动应用幂等性)
await publishArticle({
  title: '我的文章',
  content: '文章内容...'
});

// 获取文章列表(自动应用缓存)
const articles = await getArticles(1, 10);

🚀 高级功能

除了基础功能,还提供了更多高级功能:

请求去抖(Debounce)

import { createDebounceRequestor } from 'request-library';

const debouncedSearch = createDebounceRequestor(500);
// 500ms内多次调用,只执行最后一次
debouncedSearch.get('/api/search', { params: { keyword: 'test' } });

请求节流(Throttle)

import { createThrottleRequestor } from 'request-library';

const throttledLoad = createThrottleRequestor(1000);
// 1秒内无论调用多少次,只执行一次
window.onscroll = () => throttledLoad.get('/api/load-more');

请求去重(Deduplication)

import { createDedupeRequestor } from 'request-library';

const dedupeRequestor = createDedupeRequestor();
// 同时发起多个相同请求,只发送一次,共享结果
Promise.all([
  dedupeRequestor.get('/api/user/123'),
  dedupeRequestor.get('/api/user/123'),
  dedupeRequestor.get('/api/user/123')
]);

请求重试策略(Retry Strategy)

import { createRetryStrategyRequestor } from 'request-library';

const retryRequestor = createRetryStrategyRequestor({
  maxRetries: 3,
  retryDelay: (attempt) => Math.pow(2, attempt) * 1000, // 指数退避
  shouldRetry: (error) => error.response?.status >= 500,
  onRetry: (attempt, error) => console.log(`重试第${attempt}次`)
});

请求限流(Rate Limiting)

import { createRateLimitRequestor } from 'request-library';

const rateLimitedRequestor = createRateLimitRequestor({
  maxRequests: 10,
  window: 1000 // 每秒最多10个请求
});

更多高级功能请查看 高级功能文档

📖 详细文档

✨ 核心功能

1. 请求缓存

创建带有缓存的请求,支持自定义缓存键和失效策略。

import { createCacheRequestor } from './src';

const req = createCacheRequestor({
  duration: 1000 * 60 * 5, // 缓存5分钟
  key: (config) => `${config.method}:${config.url}`,
  persist: false // 使用内存缓存
});

// 第一次请求
const data1 = await req.get('/api/articles');

// 第二次请求(使用缓存)
const data2 = await req.get('/api/articles');

2. 请求幂等

保证幂等性请求不会重复提交。

import { createIdempotentRequestor } from './src';

const req = createIdempotentRequestor();

// 多次调用相同的请求,只会实际发送一次
await req.post('/api/payment', { orderId: '123', amount: 100 });
await req.post('/api/payment', { orderId: '123', amount: 100 }); // 使用缓存

3. 请求并发控制

限制同时进行的请求数量。

import { createParallelRequestor } from './src';

const req = createParallelRequestor({ maxCount: 3 }); // 最多3个并发

// 这10个请求会以3个为一组并发执行
const promises = Array.from({ length: 10 }, (_, i) => 
  req.get(`/api/data/${i}`)
);
await Promise.all(promises);

4. 请求串行控制

确保请求按顺序执行。

import { createSerialRequestor } from './src';

const req = createSerialRequestor();

// 这些请求会按顺序执行
await req.post('/api/step1');
await req.post('/api/step2');
await req.post('/api/step3');

5. 请求重试

自动重试失败的请求。

import { createRetryRequestor } from './src';

const req = createRetryRequestor(3, 1000); // 最多重试3次,每次间隔1秒

try {
  const data = await req.get('/api/unstable-endpoint');
} catch (error) {
  console.error('请求失败:', error);
}

6. 事件监听

监听请求生命周期事件。

const req = requestor;

// 监听请求前事件
req.on('beforeRequest', (config) => {
  console.log('请求即将发送:', config.url);
  // 添加认证token
  config.headers = config.headers || {};
  config.headers['Authorization'] = 'Bearer token';
});

// 监听响应事件
req.on('responseBody', (config, response) => {
  console.log('收到响应:', response.status, response.data);
});

// 监听错误事件
req.on('error', (error, config) => {
  console.error('请求错误:', error.message);
});

📝 API 文档

Requestor 接口

所有请求器都实现了 Requestor 接口:

interface Requestor {
  get<T>(url: string, options?: RequestOptions): Promise<Response<T>>;
  post<T>(url: string, data?: any, options?: RequestOptions): Promise<Response<T>>;
  put<T>(url: string, data?: any, options?: RequestOptions): Promise<Response<T>>;
  delete<T>(url: string, options?: RequestOptions): Promise<Response<T>>;
  patch<T>(url: string, data?: any, options?: RequestOptions): Promise<Response<T>>;
  on(event: string, handler: Function): void;
  off(event: string, handler: Function): void;
  emit(event: string, ...args: any[]): void;
}

RequestOptions

interface RequestOptions {
  headers?: Record<string, string>;
  params?: Record<string, any>;
  body?: any;
  timeout?: number;
  auth?: boolean;
  [key: string]: any;
}

CacheOptions

interface CacheOptions {
  key?: (config: RequestConfig) => string;
  duration?: number;
  isValid?: (key: string, config: RequestConfig) => boolean | Promise<boolean>;
  persist?: boolean;
}

🔧 高级用法

组合使用多个功能

import { 
  createFetchRequestor, 
  inject,
  createCacheRequestor,
  createParallelRequestor 
} from './src';

// 创建基础请求器
const baseRequestor = createFetchRequestor('https://api.example.com');

// 添加缓存功能
const cachedRequestor = createCacheRequestor({
  duration: 1000 * 60 * 5
})(baseRequestor);

// 添加并发控制
const finalRequestor = createParallelRequestor({ maxCount: 3 })(cachedRequestor);

inject(finalRequestor);

自定义缓存存储

import { CacheStore } from './src/types';
import { useCacheStore } from './src/request-core/store';

// 使用持久化存储
const store = useCacheStore(true); // true 表示使用 localStorage

// 自定义存储
class CustomStore implements CacheStore {
  // 实现接口方法...
}

📚 业务层使用

样板代码和补丁机制

业务层采用样板代码 + 补丁的机制:

  • templet/ 目录:自动生成的样板代码
  • patch/ 目录:手动修改的补丁代码(会覆盖样板代码)
// templet/article.ts(自动生成)
export const publishArticle = () => {
  // 基础实现
};

// patch/article.ts(手动修改)
export const publishArticle = () => {
  // 添加额外逻辑,如认证token
};

🎯 设计亮点

  1. 依赖倒置原则(DIP):核心层不依赖具体实现,通过接口抽象实现灵活切换
  2. 三层架构:清晰的职责分离,易于维护和扩展
  3. 事件系统:支持请求生命周期事件监听
  4. 类型安全:完整的 TypeScript 类型支持
  5. 组合式设计:各种功能可以灵活组合使用

📄 许可证

MIT

🤝 贡献

欢迎提交 Issue 和 Pull Request!