微信小程序网络请求进阶:从基础封装到拦截器实战

1. 为什么我们需要封装 wx.request?

如果你刚开始接触微信小程序开发,大概率会直接用 wx.request 来请求数据。代码写起来大概是这样的:

wx.request({
  url: 'https://api.example.com/data',
  method: 'GET',
  success(res) {
    console.log('请求成功', res.data)
  },
  fail(err) {
    console.error('请求失败', err)
  },
  complete() {
    console.log('请求完成')
  }
})

看起来挺简单的,对吧?但当你真正开始做一个项目时,问题就来了。想象一下这个场景:你的小程序有几十个页面,每个页面都有好几个接口要调用。每个接口你都要写一遍 wx.request,都要处理一遍 successfail。更头疼的是,很多接口都需要在请求头里带上用户的登录凭证 token,每次请求前你都得从本地存储里读一下 token,然后手动塞到 header 里。万一哪天后端说 token 的字段名要改,或者登录逻辑变了,你就得把所有用到 wx.request 的地方都改一遍,这简直就是一场灾难。

我自己就踩过这个坑。早期项目图快,到处直接写 wx.request,后来要加全局的 loading 效果、要统一处理登录过期、要切换测试和生产环境的域名,差点没改到崩溃。这就是为什么我们需要对网络请求进行封装——把那些重复的、通用的逻辑抽离出来,统一管理

封装的核心目标有三个:一是让代码更简洁,业务逻辑里只关心请求什么数据和处理什么数据;二是让维护更容易,所有公共逻辑(比如加 token、处理错误)只在一个地方修改;三是提升开发体验和用户体验,比如自动管理 loading 状态、优雅地处理并发请求。

而且,从微信小程序基础库 2.10.2 版本开始,异步 API 开始支持 Promise 风格的调用。这意味着我们可以告别“回调地狱”,用更优雅的 async/await 来写异步代码。我们的封装,就是要基于 Promise,打造一个像 axios 一样好用、甚至更贴合小程序场景的网络请求库。

2. 基础骨架:创建一个 Promise 化的请求类

万事开头难,我们先从搭建一个最基础的骨架开始。我们的思路是创建一个 Class,用面向对象的方式来组织代码,这样后续扩展属性和方法会非常方便。

2.1 创建 WxRequest 类与 request 方法

我们首先创建一个 WxRequest 类。在它的构造函数里,我们先留空,后续会在这里初始化一些默认配置。最关键的是,我们要在类里面创建一个 request 方法,这个方法将是我们所有请求的发起中心。

// utils/request.js
class WxRequest {
  constructor() {
    // 初始化工作,稍后填充
  }

  /**
   * 发起网络请求
   * @param {Object} options 请求配置,和 wx.request 的参数保持一致
   * @returns {Promise} 返回一个 Promise 对象
   */
  request(options) {
    // 核心:用 Promise 包装 wx.request
    return new Promise((resolve, reject) => {
      wx.request({
        ...options, // 展开用户传入的所有配置
        success: (res) => {
          // 请求成功时,通过 resolve 返回结果
          resolve(res)
        },
        fail: (err) => {
          // 请求失败时,通过 reject 返回错误
          reject(err)
        }
      })
    })
  }
}

// 创建类的实例并导出
const instance = new WxRequest()
export default instance

看,代码非常清晰。request 方法接收一个配置对象 options,然后内部用 new Promise 包装了 wx.request。当微信的 success 回调触发时,我们调用 resolve(res) 让外部的 Promise 变为成功状态;当 fail 回调触发时,我们调用 reject(err)Promise 变为失败状态。

2.2 在页面中使用我们封装的请求

现在,我们可以在页面中像使用 axios 一样使用它了。有两种方式,一种是传统的 .then().catch() 链式调用,另一种是更推荐的使用 async/await,让异步代码看起来像同步代码一样直观。

// pages/index/index.js
import request from '../../utils/request'

Page({
  async onLoad() {
    // 方式一:使用 async/await (推荐)
    try {
      const res = await request.request({
        url: 'https://api.example.com/data',
        method: 'GET'
      })
      console.log('获取到的数据:', res.data)
    } catch (err) {
      console.error('请求出错:', err)
    }

    // 方式二:使用 Promise 链
    request.request({
      url: 'https://api.example.com/data',
      method: 'GET'
    })
    .then(res => console.log(res.data))
    .catch(err => console.error(err))
  }
})

到这一步,我们已经实现了一个最基础的 Promise 化封装。虽然功能简单,但已经解决了最核心的“回调地狱”问题。不过,这离一个健壮的网络模块还差得远。接下来,我们要给它注入灵魂。

3. 让配置更灵活:默认参数与实例化配置

直接使用上面的封装,你会发现每次请求都要写完整的 URL,还要重复设置 headertimeout 等参数,非常麻烦。我们需要一套灵活的配置系统,允许设置全局默认值,也允许在单个请求中覆盖。

3.1 定义默认配置 (defaults)

我们在 WxRequest 类内部定义一个 defaults 对象,用来存放所有请求的默认配置。

class WxRequest {
  // 默认配置
  defaults = {
    baseURL: '', // 基础路径,如 https://api.example.com
    url: '', // 接口路径
    data: null, // 请求参数
    method: 'GET', // 默认请求方法
    header: {
      'Content-Type': 'application/j
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值