在使用 UniApp 开发微信小程序的过程中,网络请求是几乎每个项目都绕不开的核心环节 🌐。

无论是获取商品列表🛍️、提交订单📦,还是用户登录🔐、数据同步🔄,背后都离不开 uni.request 的调用。

然而,如果每次发起请求都要:

  • 手动拼接 URL 🔗

  • 添加 Token 🪪

  • 处理 401 跳转 🚪

  • 统一错误提示 ⚠️

……不仅代码冗余,还极易出错 😩。

这时候,请求拦截器与响应拦截器的价值就凸显出来了 ✨!

虽然 UniApp 并未像 Axios 那样内置完整的拦截器体系,但它提供了强大的扩展能力——通过 uni.addInterceptor,我们完全可以构建一套 高度封装、可维护、跨页面复用 的 HTTP 请求模块 💪。

🔍 一、为什么我们需要拦截器?

想象一下这些场景:

  • 所有接口都以 https://api.example.com 为前缀,你不想在每个页面重复写完整 URL;

  • 用户登录后,后续请求必须携带 Authorization: Bearer <token>

  • 网络超时时间统一设为 10 秒 ⏱️;

  • 当返回状态码为 401(未授权)时,自动清除本地登录态并跳转到登录页;

  • 接口返回 { code: '200', msg: '成功', result: {...} },你只想拿到 result 部分;

  • 网络异常或业务错误时,自动弹出轻提示(Toast),无需每个页面单独处理。

如果没有拦截器,上述逻辑将散落在各个页面中,形成大量重复代码 🧩,后期维护成本极高。

而有了拦截器,这一切都可以 集中管理、一次配置、全局生效 ✅!

⚙️ 二、UniApp 拦截器机制解析

1️.请求拦截器:uni.addInterceptor

UniApp 提供了 uni.addInterceptor(type, interceptor) 方法,用于在特定 API 调用前插入自定义逻辑。

对于网络请求,我们关注的是 'request' 类型:

uni.addInterceptor('request', {
  invoke(options: UniApp.RequestOptions) {
    // 在这里修改 options
  }
})
  • invoke 方法会在 每次调用 uni.request() 之前自动执行 🔄

  • 参数 options 是原始请求配置对象(包含 url, header, method 等)

  • 直接修改 options 即可(因为是引用传递,无需 return)💡

✅ 支持的类型还包括 'uploadFile'、'downloadFile',可根据需要注册。

2.响应拦截器:需自行封装

遗憾的是,UniApp 没有提供原生的“响应拦截器” ❌。

但我们可以在封装 uni.request 时,在 successfail 回调中统一处理响应逻辑,从而模拟出响应拦截的效果。

这正是我们接下来要做的 🎯!

🧪 三、实战:封装一个完整的 HTTP 模块

下面是一个适用于 微信小程序 + Vue 3 + TypeScript + Pinia 项目的完整示例。

1.定义基础配置与拦截器

// utils/http.ts
import { memberStore } from '@/stores'

// 后端 API 基础地址(注意:小程序不支持代理,必须写完整 HTTPS)
const BASE_URL = 'https://example.com'

// 请求拦截器:统一处理请求前的逻辑
const requestInterceptor = {
  invoke(options: UniApp.RequestOptions) {
    // 1. 自动拼接 baseURL(仅当 url 不以 http 开头时)
    if (!options.url.startsWith('http')) {
      options.url = BASE_URL + options.url
    }

    // 2. 设置默认超时时间(10 秒)
    options.timeout = 10000

    // 3. 添加通用请求头
    options.header = {
      ...options.header,
      'source-client': 'miniapp', // 标识来源为小程序
    }

    // 4. 注入用户 Token(如果已登录)
    const token = memberStore().profile?.token
    if (token) {
      options.header.Authorization = token
    }
  },
}

// 注册拦截器(同时覆盖普通请求和文件上传)
uni.addInterceptor('request', requestInterceptor)
uni.addInterceptor('uploadFile', requestInterceptor)

2.封装核心请求函数(含响应处理)

// 定义后端返回的数据结构
export interface HttpResult<T> {
  code: string          // 业务状态码,如 '200'
  msg: string           // 提示信息
  result: T             // 实际数据
}

// 封装 uni.request 为 Promise,并统一处理响应
export const http = <T>(options: UniApp.RequestOptions): Promise<HttpResult<T>> => {
  return new Promise((resolve, reject) => {
    uni.request({
      ...options,
      success(res) {
        // HTTP 状态码 2xx 表示请求成功到达服务器
        if (res.statusCode >= 200 && res.statusCode < 300) {
          // 解析业务数据
          resolve(res.data as HttpResult<T>)
        }
        // 特殊处理 401:Token 失效,跳转登录
        else if (res.statusCode === 401) {
          const store = memberStore()
          store.clearProfile() // 清除本地用户信息
          uni.navigateTo({ url: '/pages/login/login' })
          reject(res)
        }
        // 其他业务错误(如 code !== '200')
        else {
          const errMsg = (res.data as HttpResult<unknown>)?.msg || '请求失败'
          uni.showToast({ icon: 'none', title: errMsg })
          reject(res)
        }
      },
      fail(err) {
        // 网络层错误(如 DNS 解析失败、超时)
        uni.showToast({ icon: 'none', title: '网络错误,请检查网络连接' })
        reject(err)
      },
    })
  })
}

3.在页面中使用

<!-- pages/index/index.vue -->
<script setup lang="ts">
import { http } from '@/utils/http'

onLoad(async () => {
  try {
    // 发起请求,泛型指定 result 类型
    const res = await http<{ nickname: string; avatar: string }>('/member/profile')
    console.log('用户昵称:', res.result.nickname) 👤
  } catch (error) {
    // 错误已在拦截器中处理,此处可选择性记录日志
    console.error('请求异常:', error) 🐞
  }
})
</script>

⚠️四、关键注意事项

拦截器只对 uni.request 生效

如果你在项目中引入了 axios 或使用 fetch,它们 不会触发 uni.addInterceptor

因此,所有网络请求应统一走 http 函数,确保逻辑一致性 🧵。

🎉 五、总结

通过 uni.addInterceptor + 自定义 Promise 封装,我们成功在 UniApp 小程序中实现了:

  • ✅ 请求拦截:统一处理 URL、Header、Token、超时

  • ✅ 响应拦截:集中解析数据、处理 401、错误提示

  • ✅ 类型安全:TypeScript 泛型支持,开发体验更佳 🧠

  • ✅ 多端兼容:H5 可用代理,小程序直连后端

这套方案已在多个上线项目中验证,稳定可靠 💯。它不仅减少了重复代码,还极大提升了错误处理的一致性和用户体验。

希望这篇文章能帮助你在 UniApp 开发中写出更优雅、更专业的网络层代码 🧑‍💻!

如果你有任何疑问或优化建议,欢迎在评论区交流 💬~

希望这篇文章能帮助你在 UniApp 开发中写出更优雅、更专业的网络层代码 🧑‍💻!

如果你有任何疑问或优化建议,欢迎在评论区交流 💬~

📌 延伸阅读: