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

uniapp-request-sdk

v1.6.0

Published

用于uniapp小程序的请求库的sdk

Readme

uniapp-request-sdk

一个为 uni-app 小程序框架设计的高效、易用的 HTTP 请求库。支持自动重试、动态 token 管理、请求头预处理等企业级特性。

npm version license

特性

  • 自动重试机制 - 请求失败自动重试,可配置重试次数和延迟
  • 动态 Token 管理 - 支持自动获取和更新 token,兼容 APP 原生交互
  • 请求头预处理 - 支持同步/异步预处理器,动态生成或修改请求头
  • 完整的异常处理 - 统一的错误处理、HTTP 状态码处理、权限管理
  • 文件上传支持 - 专门优化的文件上传接口,独立超时控制
  • 平台兼容 - 支持 iOS App、Android App、H5 等多平台
  • TypeScript 支持 - 完整的类型定义,更好的开发体验
  • 完全向后兼容 - 不破坏现有代码,渐进式增强

安装

npm 安装

npm install uniapp-request-sdk

yarn 安装

yarn add uniapp-request-sdk

快速开始

基础使用

import UniRequest from 'uniapp-request-sdk';

// 1. 创建请求实例
const request = new UniRequest({
  baseUrl: 'https://api.example.com',
  timeout: 10000,
});

// 2. 发送 GET 请求
const data = await request.get('/users/list');

// 3. 发送 POST 请求
const result = await request.post('/users', { name: 'John' });

// 4. 发送 DELETE 请求
await request.delete('/users/1');

// 5. 发送 PUT 请求
await request.put('/users/1', { name: 'Jane' });

// 6. 上传文件
const uploadResult = await request.uploadFile(
  '/upload',
  '/path/to/file.jpg'
);

详细配置

初始化配置

const request = new UniRequest({
  // 基础配置
  baseUrl: 'https://api.example.com',           // API 基础地址(必须)
  username: 'john_doe',                           // 用户名(用于日志)

  // 超时设置
  timeout: 10000,                                 // 普通请求超时(毫秒,默认 10s)
  uploadTimeout: 5000,                            // 文件上传超时(毫秒,默认 5s)

  // 重试配置
  maxRetryCount: 3,                               // 最大重试次数(默认 3)
  retryDelay: 3000,                               // 重试延迟时间(毫秒,默认 3s)

  // 请求头配置
  header: {                                       // 全局请求头
    'Content-Type': 'application/json',
    'X-Custom-Header': 'value',
  },

  // Token 配置
  token: 'initial-token',                         // 初始 token
  tokenHeader: 'Authorization',                   // token 所在的 header 字段名(默认)
  tokenPrefix: 'Bearer ',                         // token 前缀(默认带空格)
  tokenEventName: 'getToken',                     // 向 APP 获取 token 的事件名
  getTokenFun: async () => {                      // 自定义获取 token 函数
    return await fetchTokenFromStorage();
  },

  // 错误处理
  onErrorHandler: (error) => {                    // 统一错误处理函数
    console.error('请求错误:', error);
    // 可以在这里上报错误日志
  },

  // 新增:请求头预处理
  headerProcessor: async (header) => {            // 动态处理请求头(异步)
    const timestamp = Date.now();
    const signature = await generateSignature(timestamp);
    return {
      'X-Timestamp': timestamp.toString(),
      'X-Signature': signature,
    };
  },
});

运行时修改配置

// 使用 setParams 方法动态更新配置
request.setParams({
  token: 'new-token',                             // 更新 token
  baseUrl: 'https://new-api.example.com',         // 更新 API 地址
  headerProcessor: (header) => {                  // 更新头处理器
    return {
      'X-New-Header': 'new-value',
    };
  },
});

API 文档

GET 请求

// 基础 GET 请求
const data = await request.get<ResponseType>('/users/list');

// 带查询参数
const data = await request.get<ResponseType>('/users/list', {
  page: 1,
  limit: 10,
});

// 自定义请求头
const data = await request.get<ResponseType>(
  '/users/list',
  {},
  {
    'X-Custom-Header': 'custom-value',
  }
);

POST 请求

// 基础 POST 请求
const result = await request.post<ResponseType>('/users', {
  name: 'John',
  email: '[email protected]',
});

// 自定义请求头
const result = await request.post<ResponseType>(
  '/users',
  { name: 'John' },
  {
    'X-Custom-Header': 'custom-value',
  }
);

DELETE 请求

const result = await request.delete<ResponseType>('/users/1');

PUT 请求

const result = await request.put<ResponseType>('/users/1', {
  name: 'Updated Name',
});

文件上传

// 基础文件上传
const result = await request.uploadFile<ResponseType>(
  '/upload',                              // 上传 URL
  '/path/to/file.jpg'                    // 文件路径
);

// 带 FormData 的文件上传
const result = await request.uploadFile<ResponseType>(
  '/upload',
  '/path/to/file.jpg',
  {                                       // FormData 字段
    description: 'My upload',
    category: 'profile',
  }
);

// 自定义文件字段名和请求头
const result = await request.uploadFile<ResponseType>(
  '/upload',
  '/path/to/file.jpg',
  { description: 'My upload' },
  'avatar',                               // 文件字段名(默认 'file')
  {                                       // 自定义请求头
    'X-Upload-Token': 'upload-token',
  }
);

使用示例

示例 1:基础请求

import UniRequest from 'uniapp-request-sdk';

// 创建实例
const request = new UniRequest({
  baseUrl: 'https://api.example.com',
});

// 使用
export async function getUsers() {
  try {
    const response = await request.get('/users');
    console.log('用户列表:', response);
    return response;
  } catch (error) {
    console.error('获取用户列表失败:', error);
  }
}

示例 2:Token 管理

import UniRequest from 'uniapp-request-sdk';

const request = new UniRequest({
  baseUrl: 'https://api.example.com',
  tokenEventName: 'getToken',  // APP 端事件名
  onErrorHandler: (error) => {
    if (error.statusCode === 401) {
      console.log('用户已登出');
      // 跳转到登录页
      uni.redirectTo({ url: '/pages/login/index' });
    }
  },
});

// 登录后更新 token
async function login(username: string, password: string) {
  const { token } = await request.post('/auth/login', {
    username,
    password,
  });

  // 更新 token
  request.setParams({ token });
}

示例 3:动态请求头预处理

import UniRequest from 'uniapp-request-sdk';
import { generateSignature } from './crypto';

const request = new UniRequest({
  baseUrl: 'https://api.example.com',
  headerProcessor: async (header) => {
    // 生成签名
    const timestamp = Date.now();
    const sign = await generateSignature({
      timestamp,
      token: header['Authorization'],
    });

    return {
      'X-Timestamp': timestamp.toString(),
      'X-Sign': sign,
    };
  },
});

示例 4:文件上传

import UniRequest from 'uniapp-request-sdk';

const request = new UniRequest({
  baseUrl: 'https://api.example.com',
  uploadTimeout: 30000,  // 文件上传超时 30 秒
});

// 选择文件并上传
async function selectAndUploadFile() {
  uni.chooseImage({
    count: 1,
    success: async (res) => {
      try {
        const result = await request.uploadFile(
          '/upload',
          res.tempFilePaths[0],
          {
            // 附加信息
            description: '头像',
            category: 'avatar',
          }
        );
        console.log('上传成功:', result);
      } catch (error) {
        console.error('上传失败:', error);
      }
    },
  });
}

示例 5:实时生成签名

import UniRequest from 'uniapp-request-sdk';
import CryptoJS from 'crypto-js';

// 创建带有实时签名的请求实例
const request = new UniRequest({
  baseUrl: 'https://api.example.com',
  headerProcessor: async (header) => {
    // 每次请求都生成新签名
    const timestamp = Date.now().toString();
    const appKey = 'your-app-key';

    // 根据 timestamp + appKey 生成签名
    const sign = CryptoJS.SHA256(timestamp + appKey).toString();

    return {
      'X-Timestamp': timestamp,
      'X-Sign': sign,
    };
  },
});

响应格式

库默认假定服务器返回的响应格式如下:

{
  errno: 0,              // 错误码(0 表示成功)
  data: {                // 实际数据
    // ... 业务数据
  }
}

其中:

  • errno === 0 表示请求成功
  • errno !== 0 表示业务错误,会触发 reject

错误处理

自动处理的错误

| 错误类型 | 处理方式 | |---------|---------| | HTTP 403 | 自动获取新 token 并重试 | | HTTP 401 | 触发 logout 事件,通知 APP 返回登录页 | | 网络错误 | 自动重试(最多 maxRetryCount 次) | | 超时错误 | 自动重试(最多 maxRetryCount 次) | | 业务错误 | 直接 reject,业务处理 |

全局错误处理

const request = new UniRequest({
  baseUrl: 'https://api.example.com',
  onErrorHandler: (error) => {
    // 这里处理所有请求错误
    if (error.statusCode === 401) {
      // 处理权限错误
      console.log('权限不足');
    } else if (error.errno !== undefined) {
      // 处理业务错误
      console.log('业务错误:', error.errno);
    } else {
      // 处理网络错误
      console.log('网络错误:', error.errMsg);
    }
  },
});

局部错误处理

try {
  const data = await request.get('/users');
} catch (error) {
  // 处理该请求的错误
  console.error('请求失败:', error);
}

平台差异处理

H5 平台

在 H5 平台上,请勿在请求头中设置 cookie,因为出于安全考虑,H5 中自动删除了手动设置的 cookie。

// ❌ 错误:H5 中不生效
const request = new UniRequest({
  tokenHeader: 'cookie',
});

// ✅ 正确:使用 Authorization header
const request = new UniRequest({
  tokenHeader: 'Authorization',
});

小程序平台

在小程序中,token 需要通过 sendNativeEvent 从 APP 中获取。

const request = new UniRequest({
  tokenEventName: 'getToken',  // APP 端对应事件名
});

配置参数详解

| 参数 | 类型 | 默认值 | 必填 | 说明 | |-----|------|-------|------|------| | baseUrl | string | - | ✅ | API 基础地址,支持代理路径 | | timeout | number | 10000 | - | 普通请求超时(毫秒) | | uploadTimeout | number | 5000 | - | 文件上传超时(毫秒) | | maxRetryCount | number | 3 | - | 失败重试次数 | | retryDelay | number | 3000 | - | 重试延迟时间(毫秒) | | header | object | - | - | 全局请求头 | | headerProcessor | function | - | - | 请求头预处理函数(新增) | | token | string | - | - | 初始 token | | tokenHeader | string | Authorization | - | token 所在 header 字段 | | tokenPrefix | string | 'Bearer ' | - | token 前缀 | | tokenEventName | string | getToken | - | APP 获取 token 的事件名 | | getTokenFun | function | - | - | 自定义 token 获取函数 | | username | string | - | - | 用户名(用于日志) | | onErrorHandler | function | console.error | - | 全局错误处理函数 |

请求头预处理器(新增功能)

请求头预处理器允许你在每次请求前动态生成或修改请求头,特别适合需要:

  • 动态生成签名 - 基于时间戳生成请求签名
  • 权限认证 - 根据用户权限添加特殊 header
  • 版本标记 - 添加 API 版本或协议版本
  • 业务数据 - 从业务接口获取数据并添加到 header

使用场景

场景 1:生成请求签名

const request = new UniRequest({
  baseUrl: 'https://api.example.com',
  headerProcessor: async (header) => {
    const timestamp = Date.now();
    const appSecret = 'your-app-secret';

    // 生成签名
    const sign = generateHMAC(timestamp + appSecret);

    return {
      'X-Timestamp': timestamp.toString(),
      'X-Sign': sign,
    };
  },
});

场景 2:从业务接口获取 header 数据

const request = new UniRequest({
  baseUrl: 'https://api.example.com',
  headerProcessor: async (header) => {
    // 从缓存或接口获取业务数据
    const businessData = await getBusinessDataFromStorage();

    return {
      'X-Business-Id': businessData.id,
      'X-Business-Version': businessData.version,
    };
  },
});

场景 3:同步生成请求 ID

import { v4 as uuidv4 } from 'uuid';

const request = new UniRequest({
  baseUrl: 'https://api.example.com',
  headerProcessor: (header) => {
    // 同步生成请求 ID
    return {
      'X-Request-Id': uuidv4(),
    };
  },
});

预处理器的执行时机

  • 执行点:在设置 token 后、发送请求前
  • 执行频率:每次请求都执行(包括重试)
  • 异常处理:如果预处理器异常,请求会直接 reject,不会发送

预处理器的签名

// 同步预处理器
type HeaderProcessor = (header: Record<string, string>) => Record<string, string>;

// 异步预处理器
type HeaderProcessor = (header: Record<string, string>) => Promise<Record<string, string>>;

最佳实践

✅ 推荐做法

  1. 在应用初始化时创建单一实例
// app.ts 或 main.ts
import UniRequest from 'uniapp-request-sdk';

export const request = new UniRequest({
  baseUrl: process.env.VUE_APP_API_URL,
  token: initialToken,
  username: getUserName(),
});
  1. 为不同的业务模块创建单独的方法
// api/user.ts
export function getUserList(page: number) {
  return request.get('/users', { page });
}

export function createUser(data: User) {
  return request.post('/users', data);
}
  1. 统一处理所有错误
const request = new UniRequest({
  onErrorHandler: (error) => {
    // 上报到日志系统
    logService.error(error);

    // 根据错误类型显示提示
    if (error.errno) {
      showErrorToast(error.errno);
    }
  },
});

❌ 避免做法

  1. 不要在每个请求时创建新实例
// ❌ 错误
async function getUsers() {
  const request = new UniRequest({ baseUrl: '...' });
  return request.get('/users');
}

// ✅ 正确
async function getUsers() {
  return request.get('/users');
}
  1. 不要在预处理器中执行耗时操作
// ❌ 错误:每次请求都会等待 5 秒
headerProcessor: async () => {
  await sleep(5000);  // 不必要的延迟
  return {};
}

// ✅ 正确:提前准备数据
headerProcessor: async () => {
  const cachedData = await cache.get('businessData');
  return { 'X-Business-Id': cachedData.id };
}
  1. 不要在头预处理器中设置 cookie(H5 平台)
// ❌ 错误:H5 中不生效
headerProcessor: async () => {
  return { 'cookie': 'sessionid=xxx' };
}

// ✅ 正确:使用其他方式
headerProcessor: async () => {
  return { 'X-Session-Id': 'xxx' };
}

企业级实战案例

真实案例:OA 流程审批系统

以下是基于 getui-oa-process-uniapp 项目的实战案例,展示如何在真实企业系统中使用本库。

项目背景

一个 uni-app 小程序 OA 系统,用于流程审批、预算查询等企业应用。该项目使用本库作为核心请求库。

1. 请求实例初始化

// src/requests/http/index.ts
import UniRequest from 'uniapp-request-sdk';

// 显示 Toast 提示(处理 iOS 冷启动吞掉 toast 的问题)
function showToast(title: string) {
  setTimeout(() => {
    uni.showToast({
      title,
      icon: 'none',
    });
  }, 500);
}

// 全局错误处理函数
function onErrorHandler(resData: any) {
  if (resData?.data?.errno === 2002) {
    // 业务逻辑:用户无权限
    showToast(resData.data.errmsg ?? '用户无权限');
    setTimeout(() => {
      // 关闭小程序
      uni.sendNativeEvent('closeMiniProgram', {}, () => {});
    }, 1000);
  } else if (resData?.statusCode === 403) {
    // 业务逻辑:token 失效或权限不足
    if (uni.getStorageSync('isDebug')) {
      // 调试模式跳转到 mock 页面
      uni.navigateTo({
        url: '/pages/mock/index',
      });
    } else {
      // 生产环境提示重新进入
      showToast('用户登录信息失效,请退出后重试');
    }
  } else {
    // 默认错误处理
    showToast(resData?.data?.errmsg ?? '网络异常,请退出重新进入');
  }
}

// 主请求实例(用于常规业务请求)
export const requestInstance = new UniRequest({
  timeout: 4000,                    // 请求超时 4 秒
  maxRetryCount: 2,                 // 重试 2 次
  uploadTimeout: 1000 * 60 * 2,     // 文件上传超时 2 分钟
  onErrorHandler,                   // 使用统一错误处理
});

// AI 请求实例(用于 AI 接口请求)
export const aiRequestInstance = new UniRequest({
  uploadTimeout: 1000 * 20,         // 上传超时 20 秒
  maxRetryCount: 0,                 // 不重试(AI 接口可能耗时较长)
  onErrorHandler,
});

2. 创建业务 API 层

// src/requests/severs/process.ts
import { requestInstance, aiRequestInstance } from '../http';

export const ProcessServes = {
  // 获取流程详情
  getProcessDetailes: (payload: { businessId: string }) =>
    requestInstance.post<{ data: any }>('/process/application/business/detail', payload),

  // 标记流程已读
  readProcessMessage: (payload: { businessId: string }) =>
    requestInstance.post<{ data: any }>('/process/application/business/readProcessMessage', payload),

  // 查询申请人职位
  getById: (payload: { id: string }) =>
    requestInstance.post('/usercenter/oaUser/getById', payload),

  // 撤回流程
  processRecall: (payload: { businessId: string; processCategory: string; comment: string }) =>
    requestInstance.post('/process/application/process/recall', payload),

  // 获取流程事项列表
  getProcessMatterList: (payload: any) =>
    requestInstance.post<{ data: any[] }>('/process/application/matter/list', payload),

  // 获取事项信息
  getMatterInfo: (payload: any) =>
    requestInstance.post('/process/application/matter/matterInfo', payload),

  // 流程审批
  processApprove: (payload: {
    businessId: string;
    processCategory: string;
    ccUser: string[];
    comment: string;
    pass: boolean;
    attachment: Array<{ name: string; url: string }>;
  }) =>
    requestInstance.post('/process/application/process/approve', payload),

  // 保存并审批
  processSaveAndApprove: (payload: any) =>
    requestInstance.post('/process/application/process/saveAndApprove', payload),

  // 保存流程
  processSave: (payload: {
    applicantDepartmentId: string;
    processDepartmentId: string;
    applicantId: string;
    businessData: Record<string, any>;
    processId: string;
    sponsorId: string;
    sponsorDepartmentId: string;
    processCategory: string;
    businessId?: string;
  }) =>
    requestInstance.post('/process/application/business/save', payload),

  // 申请流程
  processApply: (payload: { businessId: string; ccUser: any[]; processCategory: string }) =>
    requestInstance.post('/process/application/process/apply', payload),

  // 获取流程评论
  getProcessComments: (payload: { businessId: string }) =>
    requestInstance.post('/process/application/business/commentList', payload),

  // 获取流程表单信息
  getProcessFormInfo: (processCategory: string) =>
    requestInstance.post('/process/application/business/formInfo', { processCategory }),

  // 获取流程申请人列表
  getApplyUsers: (payload: { processCategory: string; userId: string }) =>
    requestInstance.post('/flow/assistant/getApplyUsers', {
      business: payload.processCategory,
      id: payload.userId,
    }),

  // 检查流程版本号
  checkVersion: (payload: { processCategory: string; processId: string }) =>
    requestInstance.post('/process/application/process/checkVersion', payload),

  // 获取预算包使用进度
  getBudgetInventoryProgress: (payload: {
    processCategory: string;
    departmentId: string;
    subjects: string[];
    businessLineUuids: string[];
  }) =>
    requestInstance.post('/financial/budgetInventory/budgetInventoryProgress', payload),

  // 获取业务线列表
  getBusinessLineList: () =>
    requestInstance.post('financial/businessLine/businessLineList'),

  // 获取合同详情
  getContractDetail: (payload: { contractNumber: string; businessId: string }) =>
    requestInstance.post('/financial/contract/processContractDetail', payload),

  // 获取流程文件列表
  getBusinessProcessFileList: (businessId: string) =>
    requestInstance.post<any[]>('/process/application/business/businessProcessFileList', {
      businessId,
      fileTypes: ['pdf', 'docx', 'doc'],
    }),

  // 上传音频文件并转换为流程数据(使用 AI 实例,支持长超时)
  uploadAudioToProcessData: ({ filePath, data }: any) => {
    return aiRequestInstance.uploadFile('/ds/trans/process/', filePath, data);
  },
};

3. 公共 API 服务

// src/requests/severs/common.ts
import { requestInstance } from '../http';

export const CommmonServes = {
  // 获取用户信息
  getUserInfo: async (payload: { userIds: string[] }) => {
    const data = await requestInstance.post<any>('/usercenter/oaUser/getUserInfoByIds', payload);
    return data?.data;
  },

  // 获取部门信息
  getDepartmentIdInfo: async (payload: { departmentId: string; type?: string }) => {
    const data = await requestInstance.post<any>('/usercenter/oaDepartment/getParentById', payload);
    return data?.data ?? data;
  },

  // GHR 认证
  ghrAuthentication: async (payload: {}) => {
    const data = await requestInstance.post<any>('/usercenter/ghr/authentication', payload);
    return data?.data ?? data;
  },

  // 查询关联客户
  getAssociatedCustomers: async (payload: {}) => {
    const data = await requestInstance.post<any>('/gcrm/third/relevantCust/checkContains', payload);
    return data?.data ?? data;
  },
};

4. 在 Vue 组件中使用

// 在组件中使用 API 服务
import { ProcessServes } from '@/requests/severs/process';

export default {
  data() {
    return {
      processData: null,
      loading: false,
    };
  },

  async mounted() {
    await this.loadProcessDetail();
  },

  methods: {
    async loadProcessDetail() {
      this.loading = true;
      try {
        // 使用 API 服务获取数据
        const response = await ProcessServes.getProcessDetailes({
          businessId: this.businessId,
        });
        this.processData = response;
      } catch (error) {
        // 错误处理已由全局 onErrorHandler 处理
        console.error('加载流程详情失败:', error);
      } finally {
        this.loading = false;
      }
    },

    async submitApproval() {
      try {
        // 提交审批
        await ProcessServes.processApprove({
          businessId: this.businessId,
          processCategory: this.processCategory,
          ccUser: this.ccUsers,
          comment: this.comment,
          pass: true,
          attachment: this.attachments,
        });

        uni.showToast({
          title: '审批成功',
          icon: 'success',
        });
      } catch (error) {
        console.error('审批失败:', error);
      }
    },

    async uploadAudioFile() {
      try {
        // 选择音频文件
        const res = await uni.chooseFile({
          type: 'file',
          accept: 'audio/*',
        });

        // 上传音频并转换
        const result = await ProcessServes.uploadAudioToProcessData({
          filePath: res.tempFilePaths[0],
          data: {
            processCategory: this.processCategory,
          },
        });

        // 使用 AI 转换后的数据
        this.processFormData = result;
      } catch (error) {
        console.error('上传音频失败:', error);
      }
    },
  },
};

5. 关键设计要点

多实例策略

项目使用两个不同的请求实例:

  • requestInstance: 用于常规业务请求

    • 超时时间:4 秒
    • 重试次数:2 次
    • 适合快速响应的 API
  • aiRequestInstance: 用于 AI 接口请求

    • 超时时间:20 秒(足够长时间处理 AI 计算)
    • 重试次数:0 次(避免重复处理)
    • 适合长时间处理的 API
统一错误处理

所有错误都通过 onErrorHandler 函数处理:

  • 业务错误(errno = 2002):显示错误信息,关闭小程序
  • 权限错误(statusCode = 403):引导用户重新登录
  • 其他错误:显示通用错误信息
API 层封装

将所有 API 调用封装在专门的服务文件中:

  • 统一的错误处理
  • 类型安全的请求和响应
  • 易于测试和维护
  • 便于在多个组件间复用

6. 实战总结

这个案例展示了如何在生产环境中使用本库:

多实例管理 - 根据需求创建不同配置的实例 ✅ 统一错误处理 - 全局处理所有错误,避免重复代码 ✅ API 层封装 - 将请求逻辑与业务逻辑分离 ✅ 类型安全 - 充分利用 TypeScript 的泛型机制 ✅ 易于扩展 - 新 API 添加无需修改现有代码

Q: 如何处理跨域问题?

A: 在 baseUrl 中包含代理路径,让后端或开发服务器代理请求。

const request = new UniRequest({
  baseUrl: 'https://localhost:8080/api/proxy/',  // 包含代理路径
});

Q: 如何上传多个文件?

A: 多个文件需要多次调用 uploadFile,或者一个文件一个请求。

// 方式 1:循环上传
for (const filePath of filePaths) {
  await request.uploadFile('/upload', filePath);
}

// 方式 2:并行上传(不推荐,可能导致超时)
await Promise.all(
  filePaths.map(filePath => request.uploadFile('/upload', filePath))
);

Q: 如何处理 token 过期?

A: 库会自动在收到 403 状态码时获取新 token 并重试。如需自定义逻辑:

const request = new UniRequest({
  getTokenFun: async () => {
    // 自定义获取 token 的逻辑
    const token = await refreshTokenFromServer();
    return token;
  },
});

Q: 为什么第一次请求返回 403?

A: 可能是因为初始化时没有设置 token,或 token 已过期。库会在收到 403 时自动获取新 token 并重试。

Q: 如何禁用自动重试?

A: 设置 maxRetryCount 为 0。

const request = new UniRequest({
  maxRetryCount: 0,  // 禁用重试
});

Q: headerProcessor 每次都会执行吗?

A: 是的,包括重试时都会执行。这是为了确保每次请求都获得最新的 header 值(如动态生成的签名)。

版本历史

v1.4.11

  • 新增 请求头预处理器功能 (headerProcessor)
  • 🐛 修复 原有逻辑兼容性
  • 📚 文档 完整的 README 文档

v1.4.10 及之前

  • 基础请求功能
  • Token 管理
  • 自动重试
  • 错误处理

许可证

ISC License

作者

yaojun

贡献

欢迎提交 Issue 和 Pull Request!

获取帮助

如有问题,请:

  1. 查看 常见问题
  2. 提交 GitHub Issue
  3. 联系 [email protected]