@tangyuhui/universal-http-client
v1.0.7
Published
Universal HTTP client for React and Vue projects with axios wrapper
Maintainers
Readme
Universal HTTP Client
一个基于 Axios 封装的通用 HTTP 客户端,支持 React 和 Vue 项目。
特性
- 🚀 基于 Axios 封装,功能强大
- 🔧 支持 TypeScript,类型安全
- 🎯 同时支持 React 和 Vue 项目
- 📦 支持请求/响应拦截器
- 🔄 内置 Loading 状态管理
- 🔑 自动 Token 处理
- 📋 URL 参数替换
- 🛡️ 统一错误处理
- 🎨 高度可配置
安装
npm install @tangyuhui/universal-http-client axios
# 或
yarn add @tangyuhui/universal-http-client axios基础用法
1. 简单使用(向后兼容)
import { http, apiGet, apiPost } from '@tangyuhui/universal-http-client';
// 直接使用默认实例
const result = await http.get('/api/users');
// 使用便捷方法
const users = await apiGet('/api/users');
const newUser = await apiPost('/api/users', { name: 'John' });2. 创建自定义实例
import { createHttpClient, createApiUtils } from '@tangyuhui/universal-http-client';
// 创建HTTP客户端
const httpClient = createHttpClient({
baseURL: 'https://api.example.com',
timeout: 5000,
getToken: () => localStorage.getItem('token'),
loadingHandler: {
start: (code) => console.log('Loading start:', code),
end: (code) => console.log('Loading end:', code)
}
});
// 创建API工具
const api = createApiUtils(httpClient);
// 使用
const users = await api.get('/users');
// 使用自定义loadingCode
const userProfile = await api.get('/users/{id}', { id: 123 }, {
loadingCode: 'user-profile-loading'
});3. 高级配置
import { createHttpClient, createResponseFilter } from '@tangyuhui/universal-http-client';
const httpClient = createHttpClient({
baseURL: 'https://api.example.com',
headers: {
'Custom-Header': 'value'
},
getToken: () => localStorage.getItem('authToken'),
// 自定义加载处理器
loadingHandler: {
start: (code) => {
// 显示loading,code是loading状态的唯一标识
console.log('开始loading:', code);
},
end: (code) => {
// 隐藏loading
console.log('结束loading:', code);
}
},
// 全局请求拦截
beforeRequest: (config) => {
console.log('Request:', config.url);
},
// 全局响应拦截
beforeResponse: (response) => {
console.log('Response:', response.data);
},
// 错误处理
errorHandler: (error) => {
if (error.response?.status === 401) {
// 跳转到登录页
window.location.href = '/login';
}
}
});API 参考
UniversalHttpClient
主要的HTTP客户端类。
构造函数
constructor(config?: HttpClientConfig)方法
get<T>(url, params?, config?): Promise<T>post<T>(url, params?, config?): Promise<T>put<T>(url, params?, config?): Promise<T>delete<T>(url, params?, config?): Promise<T>patch<T>(url, params?, config?): Promise<T>request<T>(method, url, param?, axiosConfig?): Promise<T>updateConfig(config): void
请求配置参数
所有HTTP方法都支持一个可选的config参数,包含以下选项:
interface RequestConfig {
loadingCode?: string; // 自定义loading状态标识码
needErrorCode?: boolean; // 是否需要在错误响应中包含错误码信息
// 其他axios配置选项...
}loadingCode 参数说明:
- 用于为特定请求自定义loading状态的唯一标识
- 如果不提供,系统会自动生成(格式:
${method}${url}) - 在loadingHandler的start和end回调中会接收到这个标识码
- 适用于需要区分不同请求loading状态的场景
needErrorCode 参数说明:
- 用于控制在请求失败时是否在错误对象中包含错误码信息
- 当设置为
true时,如果服务器返回错误响应,错误对象中会包含message属性,该属性包含详细的错误信息 - 适用于需要根据错误码进行特殊处理的场景
ApiUtils
提供便捷的API调用方法,支持URL参数替换。
// URL参数替换示例
await api.get('/users/{id}', { id: 123 }); // 实际请求:/users/123
await api.post('/users/{id}/posts', { id: 123, title: 'Hello' });
// 使用自定义loadingCode的示例
await api.get('/users/{id}', { id: 123 }, {
loadingCode: 'fetch-user-profile'
});
// 使用needErrorCode的示例
try {
await api.get('/users/{id}', { id: 123 }, {
needErrorCode: true
});
} catch (error) {
// error对象中会包含message属性,包含详细的错误信息
console.error('Error message:', error.message);
}响应过滤器
import { createResponseFilter } from '@tangyuhui/universal-http-client';
const filter = createResponseFilter({
successCondition: (response) => response.code === 200,
getErrorMessage: (response) => response.message,
loginRequiredCodes: ['401', 'TOKEN_EXPIRED'],
onLoginRequired: (errorMsg) => {
// 跳转到登录页
window.location.href = '/login';
},
onError: (errorMsg) => {
// 显示错误提示
alert(errorMsg);
}
});
// 在响应拦截器中使用
httpClient.updateConfig({
beforeResponse: async (response) => {
return filter(response.data);
}
});配置选项
HttpClientConfig
interface HttpClientConfig {
baseURL?: string; // 基础URL
timeout?: number; // 超时时间
headers?: Record<string, string>; // 默认请求头
getToken?: () => string | null; // Token获取函数
loadingHandler?: LoadingHandler; // 加载状态处理器
responseFilter?: (response: any) => Promise<any>; // 响应过滤器
errorHandler?: (error: HttpError) => void; // 错误处理器
beforeRequest?: (config: HttpRequestConfig) => void; // 全局请求拦截
beforeResponse?: (response: HttpResponse) => void; // 全局响应拦截
}LoadingHandler
interface LoadingHandler {
start: (code: string) => void; // 开始加载
end: (code: string) => void; // 结束加载
}在不同框架中使用
React 项目
// hooks/useApi.ts
import { createHttpClient, createApiUtils } from '@tangyuhui/universal-http-client';
import { useState, useEffect } from 'react';
const httpClient = createHttpClient({
baseURL: process.env.REACT_APP_API_URL,
getToken: () => localStorage.getItem('token'),
});
export const api = createApiUtils(httpClient);
// 使用
export function useUsers() {
const [users, setUsers] = useState([]);
const [loading, setLoading] = useState(false);
useEffect(() => {
const fetchUsers = async () => {
setLoading(true);
try {
const data = await api.get('/users', {}, {
loadingCode: 'fetch-users-list'
});
setUsers(data);
} finally {
setLoading(false);
}
};
fetchUsers();
}, []);
return { users, loading };
}Vue 3 项目
// composables/useApi.ts
import { createHttpClient, createApiUtils } from '@tangyuhui/universal-http-client';
import { ref } from 'vue';
const httpClient = createHttpClient({
baseURL: import.meta.env.VITE_API_URL,
getToken: () => localStorage.getItem('token'),
});
export const api = createApiUtils(httpClient);
// 使用
export function useUsers() {
const users = ref([]);
const loading = ref(false);
const fetchUsers = async () => {
loading.value = true;
try {
users.value = await api.get('/users', {}, {
loadingCode: 'vue-fetch-users'
});
} finally {
loading.value = false;
}
};
return { users, loading, fetchUsers };
}迁移指南
如果你正在从项目中的本地HTTP工具迁移到这个包:
1. 安装包
npm install @tangyuhui/universal-http-client2. 替换导入
原来:
import { http } from "/@/utils/http";
import { apiGet, apiPost } from "/@/utils/http/request";现在:
import { http, apiGet, apiPost } from '@tangyuhui/universal-http-client';3. 配置迁移
原来的配置可以这样迁移:
import { createHttpClient, createApiUtils, createResponseFilter } from '@tangyuhui/universal-http-client';
// 迁移配置
const httpClient = createHttpClient({
baseURL: '', // 原来的baseURL
timeout: 10000,
getToken: () => getToken(), // 原来的getToken函数
loadingHandler: {
start: (code) => window.$wait.instance.start(code),
end: (code) => window.$wait.instance.end(code)
}
});
// 使用原来的httpFilter
const responseFilter = createResponseFilter({
onLoginRequired: (errorMsg, errorCode) => {
if (errorCode === "027004008" || errorCode === "027004007" || errorCode === "026001001") {
router.push({ path: "/login" });
}
}
});axios版本
0.15.3
许可证
EventLog 类型
项目现在包含一个 EventLog 类型,用于表示HTTP请求的日志信息:
interface EventAttr {
url: string;
params: any;
method: string;
responseData: any;
responseCode: string | number;
responseMessage: string;
responseTraceId: string;
}
interface EventLog {
eventName: string;
eventId: string;
desc: string;
curTime: number;
eventAttr: EventAttr;
traceId: string;
}这个类型可以通过 logRequestMsg 函数生成:
import { logRequestMsg } from '@tangyuhui/universal-http-client';
const eventLog = logRequestMsg(response, 'API_CALL_');
console.log(eventLog.eventName); // 输出事件名称
console.log(eventLog.eventAttr.url); // 输出请求URLMIT
