《Uniapp-Vue 3-TS 实战开发》构建HTTP请求拦截器

news2025/4/15 14:25:08

引言

        在 UniApp 结合 TypeScript 和 Vue3 的项目开发中,请求拦截器起着至关重要的作用。它能够在请求发送前和响应接收后对数据进行统一处理,极大地提高了代码的可维护性和功能性。本文将详细解析上述代码中请求拦截器的实现及其在 UniApp-Ts-Vue3 项目中的应用,让您更直观地理解其工作流程。

一、请求拦截器的作用

        请求拦截器主要用于在请求发送到服务器之前对请求进行预处理,以及在接收到服务器响应后对响应进行后处理。在我们的代码中,它实现了以下几个关键功能:

(一)基础 URL 补全

if (!options.url.startsWith('https://')) {
  options.url = baseURLhttp + options.url;
}

      当请求的 URL 不是以 https:// 开头时,会自动将基础 URL中的 baseURLhttp(项目中发起https的请求头) (比如:https://11.12.55.666666:8080)拼接在前面。这确保了所有请求都使用正确的基础路径,尤其在开发和上线不同环境切换时,能方便地统一管理请求地址。例如,若我们有一个相对路径的请求 '/api/user',经过拦截器处理后会变为:    

 'https://11.12.55.666666:8080/api/user'。

(二)设置请求超时

options.timeout = TIMEOUT

        设置了请求的超时时间为 TIMEOUT(30000 毫秒,即 30 秒)。这是一个很重要的设置,防止请求因为网络问题或服务器故障而长时间等待,提升用户体验。当请求超过 30 秒还未得到响应时,会触发 fail 回调,提示用户网络连接失败。

(三)添加小程序端请求头标识

options.header = {
  'source - client':'miniapp',
  ...options.header, // 允许覆盖默认 header
}

        在请求头中添加了 source - client 字段,值为 miniapp,用于标识该请求来自小程序端。同时,通过 ...options.header 保留了原有的请求头信息,这样既添加了自定义标识,又不会影响其他可能需要的请求头设置。例如,在服务器端可以根据这个标识对来自小程序的请求进行特定的处理。

(四)添加 token 请求头标识

const memberStore = useMemberStore()
const token = memberStore.profile?.token
if (token) {
  options.header.token = token
}

        从状态管理(这里使用的是 Pinia 库的 useMemberStore)中获取用户的 token,并将其添加到请求头的 token 字段中。这样,服务器可以通过验证 token 来确认用户身份,实现对受保护资源的访问控制。比如,用户在登录成功后,token 被存储在状态管理中,后续的请求通过拦截器自动带上 token,无需在每个请求中手动添加。

二、拦截器的实现与注册

(一)拦截器定义

const httpInterceptor = {
  // 拦截前触发
  invoke(options: UniApp.RequestOptions) {
    // 一系列处理逻辑
  },
}

        这里定义了一个名为 httpInterceptor 的拦截器对象,它包含一个 invoke 方法。invoke 方法在每次请求被拦截时触发,接收一个 options 参数,类型为 UniApp.RequestOptions,这个参数包含了本次请求的所有配置信息,我们可以在这个方法中对这些配置进行修改。

(二)拦截器注册

uni.addInterceptor('request', httpInterceptor)
uni.addInterceptor('uploadFile', httpInterceptor)

        通过 uni.addInterceptor 方法将 httpInterceptor 注册到 request 和 uploadFile 这两种请求类型上。这意味着无论是普通的 request 请求(如获取数据、提交表单等),还是 uploadFile 文件上传请求,都会经过 httpInterceptor 的处理。

三、封装请求函数

(一)函数定义与返回值

type Data<T> = {
  categorys(categorys: any): unknown
  code: string
  msg: string
  result: T
}
// 2.2 添加类型,支持泛型
export const http = <T>(options: UniApp.RequestOptions) => {
  //1.返回Promise对象
  return new Promise<Data<T>>((resolve, reject) => {
    // 请求处理逻辑
  })
}

        定义了一个名为 http 的函数,它是对 uni.request 的封装。通过泛型 <T> 支持不同类型的响应数据。函数返回一个 Promise 对象,这样可以使用 async/await 语法来处理异步请求,使代码更简洁易读。Data<T> 类型定义了响应数据的结构,包含 code(状态码)、msg(错误信息)、result(实际数据,其类型由泛型 T 决定)以及一个 categorys 函数(这里可能是特定业务需求的函数定义,具体功能需根据业务进一步分析)。

(二)请求成功处理

success(res) {
  if (res.statusCode >= 200 && res.statusCode < 300) {
    // 获取数据成功, 调用resolve
    resolve(res.data as Data<T>)
  } else if (res.statusCode === 401) {
    // 401错误  -> 清理用户信息,跳转到登录页等,具体看你的需求逻辑
    handleUnauthorized()
    reject(res)
  } else {
    // 其他HTTP错误 -> 根据后端错误信息轻提示
    const errMsg = getHttpErrorMsg(res.statusCode)
    uni.showToast({ icon: 'none', title: errMsg })
    reject(res)
  }
}

        在 uni.request 的 success 回调中,首先判断响应状态码 statusCode。如果状态码在 200 到 299 之间,表示请求成功,将响应数据转换为 Data<T> 类型后调用 resolve,将数据传递出去。若状态码为 401,表示用户未授权,调用 handleUnauthorized 函数清理用户信息并跳转到登录页面,同时调用 reject 拒绝 Promise,传递错误响应。对于其他状态码,通过 getHttpErrorMsg 函数获取对应的错误信息,并使用 uni.showToast 进行轻提示,然后拒绝 Promise。

(三)请求失败处理

fail(err) {
  uni.showToast({
    icon: 'none',
    title: '网络连接失败',
  })
  reject(err)
}

        当请求失败(如网络故障、超时等),在 fail 回调中使用 uni.showToast 提示用户网络连接失败,并调用 reject 拒绝 Promise,传递错误信息。

四、辅助函数

(一)处理 401 未授权

const handleUnauthorized = () => {
  const memberStore = useMemberStore()
  memberStore.clearProfile()
  uni.navigateTo({ url: '/pages/login/login' })
  uni.showToast({ icon: 'none', title: '登录已过期' })
}

handleUnauthorized 函数在用户遇到 401 未授权错误时被调用。它从状态管理中获取 memberStore,调用 clearProfile 方法清理用户信息,然后使用 uni.navigateTo 跳转到登录页面,并通过 uni.showToast 提示用户登录已过期。

(二)获取 HTTP 错误信息

const getHttpErrorMsg = (code: number): string => {
  const messages: Record<number, string> = {
    400: '请求参数错误',
    403: '禁止访问',
    404: '资源不存在',
    500: '服务器错误',
    502: '网关错误'
  }
  return messages[code] || `请求失败(${code})`
}

getHttpErrorMsg 函数根据传入的 HTTP 状态码 code 返回对应的错误信息。它通过一个 Record 类型的 messages 对象存储常见状态码对应的错误描述。如果状态码在 messages 中存在,则返回对应的描述;否则返回通用的错误提示 请求失败(${code})

五、工作流程示意图

        从发起,经过拦截器处理,到服务器响应,再经过拦截器处理返回给调用者的整个流程,包括基础 URL 补全、请求头添加、超时设置等在流程中的位置]

六、总结

        通过上述代码和详细解析,我们深入了解了在 UniApp-Ts-Vue3 项目中如何构建和使用请求拦截器。请求拦截器不仅能简化请求处理逻辑,还能统一管理请求相关的配置和错误处理,提升项目的开发效率和稳定性。在实际项目中,我们可以根据具体业务需求进一步扩展和优化拦截器的功能,使其更好地服务于整个应用程序。

最后,附上完整代码:

​
/**
 * 添加拦截器:
 *   拦截 request 请求
 *   拦截 uploadFile 文件上传
 *
 * TODO:
 *   1. 非 http 开头需拼接地址
 *   2. 请求超时
 *   3. 添加小程序端请求头标识
 *   4. 添加 token 请求头标识
*/
import { useMemberStore } from '@/stores'

const baseURLhttp = 'https://11.12.55.666666:8080'; //后期注意要申请SSL证书,上线小程序的请求必须是https类型的
const TIMEOUT = 30000; // 请求超时 默认 30秒 超时

//request请求拦截
const httpInterceptor = {
  // 拦截前触发
  invoke(options: UniApp.RequestOptions) {
    //1. 补全基础路径(非 https 开头时)
    if (!options.url.startsWith('https://')) {
      options.url = baseURLhttp + options.url;
    }
	
	//设置超时时间
    options.timeout = TIMEOUT
	
    //3.添加小程序请求头
    options.header = {
      'source-client': 'miniapp',
	  ...options.header, // 允许覆盖默认 header
    }
    //4.自动添加 token 信息到请求头
    const memberStore = useMemberStore()
    const token = memberStore.profile?.token
    if (token) {
      options.header.token = token
    }
    //输出options
    // console.log(options)
  },
}

// 拦截 request 请求
uni.addInterceptor('request', httpInterceptor)
// 拦截 uploadFile 文件上传
uni.addInterceptor('uploadFile', httpInterceptor)

/**
 * 封装请求函数
 * @param  UniApp.RequestOptions
 * @returns Promise
 *  1. 返回 Promise 对象
 *  2. 获取数据成功
 *    2.1 提取核心数据 res.data
 *    2.2 添加类型,支持泛型
 *  3. 获取数据失败
 *    3.1 401错误  -> 清理用户信息,跳转到登录页
 *    3.2 其他错误 -> 根据后端错误信息轻提示
 *    3.3 网络错误 -> 提示用户换网络
*/

type Data<T> = {
  categorys(categorys: any): unknown
  code: string
  msg: string
  result: T
}
// 2.2 添加类型,支持泛型
export const http = <T>(options: UniApp.RequestOptions) => {
  //1.返回Promise对象
  return new Promise<Data<T>>((resolve, reject) => {
    uni.request({
      ...options,
      //2.请求成功
      success(res) {
        // if (res.statusCode == 0 || (res.statusCode >= 200 && res.statusCode < 300)) {
        if (res.statusCode >= 200 && res.statusCode < 300) {
          // 获取数据成功, 调用resolve
          resolve(res.data as Data<T>)
        } else if (res.statusCode === 401) {
          // 401错误  -> 清理用户信息,跳转到登录页
		  handleUnauthorized()
          reject(res)
        } else {
          // 其他HTTP错误 -> 根据后端错误信息轻提示
		  const errMsg = getHttpErrorMsg(res.statusCode)
		  uni.showToast({ icon: 'none', title: errMsg })
          reject(res)
        }
      },
      // 响应失败
      fail(err) {
        uni.showToast({
          icon: 'none',
          title: '网络连接失败',
        })
        reject(err)
      },
    })
  })
}

/**
 * 处理 401 未授权
 */
const handleUnauthorized = () => {
  const memberStore = useMemberStore()
  memberStore.clearProfile()
  uni.navigateTo({ url: '/pages/login/login' })
  uni.showToast({ icon: 'none', title: '登录已过期' })
}

/**
 * 获取 HTTP 错误信息
 */
const getHttpErrorMsg = (code: number): string => {
  const messages: Record<number, string> = {
    400: '请求参数错误',
    403: '禁止访问',
    404: '资源不存在',
    500: '服务器错误',
    502: '网关错误'
  }
  return messages[code] || `请求失败(${code})`
}

​

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2332169.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

从PDF中提取表格:以GB/T2260—2007为例

文章目录 先说结论前因后果思路1、PDF2CSV2、PDF2MD → MD2CSV3、针对不同表格的两种思路1&#xff09; 竖形三线表2&#xff09;五元素为一组 还没结束批量处理1、分割markdown文档2、跳过另一种格式的文档 总结一下 先说结论 结论就是&#xff0c;博主用了一天的时间去研究如…

初识MySQL · 复合查询(内外连接)

目录 前言&#xff1a; 基本查询回顾 笛卡尔积和子查询 笛卡尔积 内外连接 子查询 单行子查询 多行子查询 多列子查询 from中使用子查询 合并查询 前言&#xff1a; 在前文我们学习了MySQL的基本查询&#xff0c;就是简单的套用了select语句&#xff0c;最多不过是…

辛格迪客户案例 | 北京舒曼德医药实施电子合约系统(eSign)

01 北京舒曼德医药科技开发有限公司&#xff1a;医药科技的数字化先锋 北京舒曼德医药科技开发有限公司&#xff08;以下简称“舒曼德医药”&#xff09;作为国内医药科技领域的领军企业&#xff0c;致力于创新药物的研发、临床试验和市场推广。公司以“科技兴药、质量为先、服…

Python面向对象-开闭原则(OCP)

1. 什么是开闭原则&#xff1f; 开闭原则(Open-Closed Principle, OCP) 是面向对象设计的五大SOLID原则之一&#xff0c;由Bertrand Meyer提出。其核心定义是&#xff1a; “软件实体(类、模块、函数等)应该对扩展开放&#xff0c;对修改关闭。” 对扩展开放&#xff1a;当需求…

Class 文件和类加载机制

一、Class 文件 与 类加载机制 概述 什么是 Class 文件&#xff1f; Java 源码&#xff08;.java&#xff09;经过 javac 编译器 编译生成的字节码文件&#xff08;.class&#xff09;&#xff1b;由 JVM 识别执行&#xff0c;包含类的完整结构信息&#xff08;如字段、方法、…

Vue3+Vite+TypeScript+Element Plus开发-07.Mockjs引用与Axios封装

系列文档目录 Vue3ViteTypeScript安装 Element Plus安装与配置 主页设计与router配置 静态菜单设计 Pinia引入 Header响应式菜单缩展 Mockjs引用与Axios封装 登录设计 登录成功跳转主页 多用户动态加载菜单 Pinia持久化 动态路由-配置 文章目录 目录 系列文档目…

【Redis】背景知识

一、Redis的特性 Redis是一种基于键值对&#xff08;key-value&#xff09;的NoSQL数据库&#xff0c;与很多键值对数据库不同的是&#xff0c;Redis中的值可以是由string&#xff08;字符串&#xff09;&#xff0c;hash&#xff08;哈希&#xff09;&#xff0c;list&#xf…

航电系统的任务载荷集成技术要点概述!

一、任务载荷集成技术难点 1. 接口标准化与兼容性 异构设备协议冲突&#xff1a;不同厂商的载荷设备&#xff08;如光学相机、雷达、电子战模块&#xff09;采用不同的通信协议&#xff08;如1553B、RS422、以太网&#xff09;&#xff0c;需设计统一的总线接口标准以支持即…

OceanBase V4.3.5 上线全文索引功能,让数据检索更高效

近日&#xff0c;OceanBase 4.3.5 BP1 版本正式推出了企业级全文索引功能。该版本在中文分词、查询效率及混合检索能力上进行了全面提升。经过自然语言模式和布尔模式在不同场景下的对比测试&#xff0c;OceanBase 的全文索引性能明显优于 MySQL。 点击下载 OceanBase 社区版…

Qt中的信号与槽及其自定义

信号源&#xff1a;哪个控件发的信号 信号的类型&#xff1a;用户进行不同的操作就会触发不同的信号 如点击按钮&#xff0c;在输入框移动光标&#xff0c;勾选一个复选框&#xff0c;选 择一个下拉框 信号的处理方式&#xff1a;槽(slot)----也就是函数&#xff0c;Qt中用con…

【PFPGA学习】状态机思想编程HDLbitsFPGA练习

目录 一、用状态机实现LED流水灯 1.1状态机思想 1.2状态机思想LED流水灯 1.3 modesim仿真 1.4 FPGA烧录实现 二、CPLD和FPGA芯片 1. 核心结构与技术原理 2. 性能与容量 3. 适用场景 &#xff14;. 选型建议 三、HDLbitsFPGA练习记录&#xff08;combinational logic…

Android 中集成 Unity 工程的步骤

在 Adroid 项目中集成 Unity 工程,主要步骤如下: 一、前提条件 1、已有一个 Android 工程项目; 2、Unity 工程已导出为 Android 工程,目录大概如下: 二、集成步骤 1、在 Android 工程中导入 Unity 工程的 unityLibrary 模块。 在 Android Studio 中,点击菜单栏 Fil…

Python从入门到精通全套视频教程免费

概述 &#x1f4e2; 所有想学Python的小伙伴看过来&#xff01;作为深耕编程领域的技术分享者&#xff0c;最新整理了一份Python从0到1的视频教程。 &#x1f4a1;亮点 ✅ 保姆级系统路线&#xff1a;从环境搭建、语法精讲&#xff0c;到爬虫/数据分析/AI/Web全栈开发&#…

蓝桥杯:对字符串处理常用知识笔记

一、前面四个是计算带有空格字符串的的长度计算 C语言代码 #include<string.h> #include<stdio.h> int main() { char s[105]; gets(s); printf("%d", strlen(s)); return 0; } 算法2 C 代码&#xff08;常用&#xff09; #include <iostream> #in…

实现一个 Markdown 编辑器组件:Vue 3 + Vite + Highlight.js

文章目录 一、项目背景与需求分析二、搭建基础项目1. 初始化 Vue 3 项目2. 安装依赖 三、实现 Markdown 编辑器组件1. 创建 Markdown 编辑器组件2. 组件说明 四、优化与拓展1. 自动保存功能2. 文件上传功能 五、总结 一、项目背景与需求分析 在现代前端开发中&#xff0c;Mark…

帆软fvs文件中某表格新增数据来声提醒

1.上传音频文件到帆软安装目录的指定环境 准备一个音频文件&#xff08;如 mp3 格式&#xff09;&#xff0c;并将其放置在合适的目录。 例如&#xff1a;%FR_HOME%\webapps\webroot\help 2.点击 FVS 模板左上角「模板>页面加载结束事件」&#xff0c;输入以下 JavaScript …

从零用java实现 小红书 springboot vue uniapp (11)集成AI聊天机器人

前言 移动端演示 http://8.146.211.120:8081/#/ 管理端演示 http://8.146.211.120:8088/#/ 项目整体介绍及演示 前面的文章我们主要完成了基础模块的开发 这次我们跟一下热点 创建AI聊天机器人 并嵌入到我们的uniapp中 首先需要了解dify我已经完成了搭建win10 VMware安装ubuntu…

$_POST 超级全局变量

$_POST 是一个超级全局变量&#xff0c;在 PHP 中用于收集通过 HTTP POST 方法发送到服务器的数据。与 $_GET 不同&#xff0c;$_POST 允许发送大量数据&#xff0c;且数据不会显示在 URL 中&#xff0c;因此更适用于提交敏感信息&#xff0c;如用户登录信息、表单数据等。 使…

开发一个环保回收小程序需要哪些功能?环保回收小程序

废品分类展示与识别 详细分类列表&#xff1a;清晰展示常见废品类型&#xff0c;如废纸&#xff08;报纸、书本纸、包装纸等&#xff09;、塑料&#xff08;塑料瓶、塑料容器、塑料薄膜等&#xff09;、金属&#xff08;易拉罐、铁制品、铜制品等&#xff09;、玻璃&#xff0…

Debezium嵌入式连接postgresql封装服务

文章目录 1.项目结构&#xff1a;2.依赖&#xff1a;3.application.properties4.DebeziumConnectorConfig类5.TableEnum类6.TableHandler接口&#xff08;表处理抽象&#xff09;7.DefaultTableHandler默认实现类8.UserTableHandler处理类9.TableHandlerFactory工厂10.Debezium…