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

@creekjs/request

v1.0.2

Published

基于 Axios 的增强型 HTTP 请求库,提供插件系统和丰富的功能扩展。

Readme

@creekjs/request

基于 Axios 的增强型 HTTP 请求库,提供插件系统和丰富的功能扩展。

特性

  • 🚀 基于 Axios,保持 API 兼容性
  • 🔌 插件系统,支持功能扩展
  • 🔄 内置防重复请求插件
  • ⏳ 内置加载状态管理插件
  • 🛠️ 支持多实例管理
  • 📦 TypeScript 支持

安装

npm install @creekjs/request
# 或
yarn add @creekjs/request

基础用法

import { request } from '@creekjs/request';

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

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

// 使用配置对象
const response = await request({
  url: '/api/users',
  method: 'GET',
  params: { page: 1, size: 10 }
});

插件系统

使用内置插件

import { request, plugins } from '@creekjs/request';

// 使用加载插件
request.pluginManager.use(new plugins.LoadingPlugin({
  showLoading: () => console.log('开始加载...'),
  hideLoading: () => console.log('加载完成')
}));

// 使用防重复请求插件
request.pluginManager.use(new plugins.DuplicatePlugin());

自定义插件

import { plugins } from '@creekjs/request';

class LoggerPlugin extends plugins.AxiosPlugin {
  beforeRequest(config) {
    console.log('请求开始:', config.url);
    return config;
  }

  afterRequest(response) {
    console.log('请求成功:', response.config.url);
    return response;
  }

  onError(error) {
    console.error('请求失败:', error.config?.url);
    return Promise.reject(error);
  }
}

// 使用自定义插件
request.pluginManager.use(new LoggerPlugin());

API 参考

request 对象

// 主要方法
request(config: AxiosRequestConfig): Promise<AxiosResponse>
request.get(url: string, config?: AxiosRequestConfig): Promise<AxiosResponse>
request.post(url: string, data?: any, config?: AxiosRequestConfig): Promise<AxiosResponse>
request.put(url: string, data?: any, config?: AxiosRequestConfig): Promise<AxiosResponse>
request.delete(url: string, config?: AxiosRequestConfig): Promise<AxiosResponse>

// 实例管理
request.instance: AxiosInstance
request.pluginManager: AxiosPluginManager
request.createInstance(config?: AxiosRequestConfig): typeof request

插件基类

abstract class AxiosPlugin {
  // 插件初始化
  init?(instance: AxiosInstance): void;
  
  // 请求前钩子
  beforeRequest?(config: AxiosRequestConfig): AxiosRequestConfig | Promise<AxiosRequestConfig>;
  
  // 请求后钩子
  afterRequest?(response: AxiosResponse): AxiosResponse | Promise<AxiosResponse>;
  
  // 错误处理钩子
  onError?(error: AxiosError): any;
}

插件管理器

class AxiosPluginManager {
  // 注册插件
  use(plugin: AxiosPlugin): void;
  
  // 设置拦截器(内部使用)
  setupInterceptors(instance: AxiosInstance): void;
}

内置插件

LoadingPlugin - 加载状态管理

interface LoadingPluginOptions {
  showLoading: () => void;    // 显示加载状态
  hideLoading: () => void;    // 隐藏加载状态
}

const loadingPlugin = new plugins.LoadingPlugin({
  showLoading: () => {
    // 显示全局加载指示器
    document.getElementById('loading').style.display = 'block';
  },
  hideLoading: () => {
    // 隐藏全局加载指示器
    document.getElementById('loading').style.display = 'none';
  }
});

request.pluginManager.use(loadingPlugin);

特性:

  • 自动管理请求计数
  • 支持并发请求的加载状态
  • 请求完成或失败时自动隐藏加载状态

DuplicatePlugin - 防重复请求

const duplicatePlugin = new plugins.DuplicatePlugin();
request.pluginManager.use(duplicatePlugin);

// 快速连续发送相同请求,只有第一个会执行
request.get('/api/users'); // 执行
request.get('/api/users'); // 被阻止
request.get('/api/users'); // 被阻止

特性:

  • 基于请求 URL、方法和参数生成唯一标识
  • 自动管理请求队列
  • 请求完成后自动清理

高级用法

创建多个实例

import { request } from '@creekjs/request';

// 创建 API 实例
const apiRequest = request.createInstance({
  baseURL: 'https://api.example.com',
  timeout: 5000,
  headers: {
    'Authorization': 'Bearer token'
  }
});

// 创建上传实例
const uploadRequest = request.createInstance({
  baseURL: 'https://upload.example.com',
  timeout: 30000
});

// 为不同实例配置不同插件
apiRequest.pluginManager.use(new plugins.DuplicatePlugin());
uploadRequest.pluginManager.use(new plugins.LoadingPlugin({
  showLoading: () => console.log('上传中...'),
  hideLoading: () => console.log('上传完成')
}));

请求拦截器

// 请求拦截器
request.instance.interceptors.request.use(
  (config) => {
    // 添加认证头
    const token = localStorage.getItem('token');
    if (token) {
      config.headers.Authorization = `Bearer ${token}`;
    }
    return config;
  },
  (error) => Promise.reject(error)
);

// 响应拦截器
request.instance.interceptors.response.use(
  (response) => {
    // 统一处理响应数据
    return response.data;
  },
  (error) => {
    // 统一错误处理
    if (error.response?.status === 401) {
      // 跳转到登录页
      window.location.href = '/login';
    }
    return Promise.reject(error);
  }
);

与 React 集成

// hooks/useApi.ts
import { useState, useEffect } from 'react';
import { request } from '@creekjs/request';

export function useApi<T>(url: string) {
  const [data, setData] = useState<T | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<Error | null>(null);

  useEffect(() => {
    const fetchData = async () => {
      try {
        setLoading(true);
        const response = await request.get(url);
        setData(response.data);
      } catch (err) {
        setError(err as Error);
      } finally {
        setLoading(false);
      }
    };

    fetchData();
  }, [url]);

  return { data, loading, error };
}

// 使用
function UserList() {
  const { data: users, loading, error } = useApi<User[]>('/api/users');

  if (loading) return <div>加载中...</div>;
  if (error) return <div>错误: {error.message}</div>;
  
  return (
    <ul>
      {users?.map(user => (
        <li key={user.id}>{user.name}</li>
      ))}
    </ul>
  );
}

最佳实践

1. 统一错误处理

class ErrorHandlerPlugin extends plugins.AxiosPlugin {
  onError(error) {
    const { response } = error;
    
    switch (response?.status) {
      case 401:
        // 未授权,跳转登录
        this.redirectToLogin();
        break;
      case 403:
        // 无权限
        this.showMessage('无权限访问');
        break;
      case 500:
        // 服务器错误
        this.showMessage('服务器错误,请稍后重试');
        break;
      default:
        this.showMessage(error.message || '请求失败');
    }
    
    return Promise.reject(error);
  }
  
  private redirectToLogin() {
    window.location.href = '/login';
  }
  
  private showMessage(message: string) {
    // 显示错误消息
    console.error(message);
  }
}

2. 请求重试

class RetryPlugin extends plugins.AxiosPlugin {
  constructor(private maxRetries = 3) {
    super();
  }
  
  async onError(error) {
    const config = error.config;
    
    if (!config || config.__retryCount >= this.maxRetries) {
      return Promise.reject(error);
    }
    
    config.__retryCount = (config.__retryCount || 0) + 1;
    
    // 延迟重试
    await new Promise(resolve => setTimeout(resolve, 1000 * config.__retryCount));
    
    return request(config);
  }
}

3. 缓存插件

class CachePlugin extends plugins.AxiosPlugin {
  private cache = new Map();
  
  beforeRequest(config) {
    if (config.method === 'get') {
      const key = this.getCacheKey(config);
      const cached = this.cache.get(key);
      
      if (cached && Date.now() - cached.timestamp < 60000) { // 1分钟缓存
        return Promise.resolve(cached.data);
      }
    }
    
    return config;
  }
  
  afterRequest(response) {
    if (response.config.method === 'get') {
      const key = this.getCacheKey(response.config);
      this.cache.set(key, {
        data: response,
        timestamp: Date.now()
      });
    }
    
    return response;
  }
  
  private getCacheKey(config) {
    return `${config.method}:${config.url}:${JSON.stringify(config.params)}`;
  }
}

许可证

ISC