微信小程序开发小技巧:微信请求 Promise 化

2021-08-1907:47:16APP与小程序开发Comments1,243 views字数 3133阅读模式

2.1 使用现成的库

安装 Promise 库 wx-promise-pro,记得一定要带 -s 或 --production,要不然无法构建成功。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/22172.html

npm i -S wx-promise-pro

然后在 app.js 中:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/22172.html

import { promisifyAll } from 'wx-promise-pro'

promisifyAll()  // promisify all wx api

App({ ... })

之后就可以正常使用了:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/22172.html

wx.pro.showLoading({
    title: '加载中',
    mask: true
})
  .then(() => console.log('in promise ~'))

2.2 自己实现

其实我们可以自己来实现一个这样的库,原理很简单,以原生 API 的 wx.request 为例:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/22172.html

// 原生 API 使用方式
wx.request({
    url: '',     // 请求的 url
    data: {},    // 参数
    method: '',  // post、get
    success: res => {
        // 请求成功回调函数,res为回调参数
    },
    fail: res => {
        // 请求失败回调函数,res为回调参数
    }
})

如果我们将其 Promise 化,应该的调用方式希望是:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/22172.html

// Promise 化后的期望使用方式
wx.pro.request({
    url: '',     // 请求的 url
    data: {},    // 参数
    method: ''   // post、get
})
  .then(res => {
      // 请求成功回调函数,res为回调参数
  })
  .catch(res => {
      // 请求失败回调函数,res为回调参数
  })

并且 then 函数返回的是一个 Promise 对象,让这个函数可以不断链式调用下去,所以首先需要 new 出来一个 Promise 对象:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/22172.html

function request(opt) {
    return new Promise((resolve, reject) => {
        wx.request({
            ...opt,
            success: res => { resolve(res)},
            fail: res => {reject(res)}
        })
    })
}

这里代码我们可以进一步改进,由于 successfail 这里传入的参数只是由 resolvereject 方法执行了下,所以可以直接传入 resolvereject 方法即可。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/22172.html

另外,由于其他小程序原生 API 格式一致,所以我们可以使用柯里化方法,来将其他需要进行 Promise 化的 API 进行处理:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/22172.html

function promisify(api) {
    return (opt = {}) => {
        return new Promise((resolve, reject) => {
            api({
                ...opt,
                fail: reject,
                success: resolve
            })
        })
    }
}

然后,将柯里化方法执行的结果作为新的 Promise 化的 API 挂载到 wx.pro 对象上:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/22172.html

// 将指定 API 进行 Promise 化
wx.pro.request = promisify(wx.request)

// 使用
wx.pro.request({...})
    .then(...)

然后为了方便我们使用其他方法,可以循环将 wx 对象上可以被 Promise 化的方法比如 requestscanCodeshowToastgetUserInfo 等一一挂载到 wx.pro 对象上,使用时可以直接 wx.pro.xx,由于这个方法执行返回的是一个 Promise 对象,因此可以像其它 Promise 化的对象那样使用。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/22172.html

事实上,不知不觉,我们就自己实现了 wx-promise-pro 的源码,这个库的核心代码也就是上面那这几行 ?文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/22172.html

2.3 在项目中使用

有了上面的工具后,我们可以将其使用在项目中,为了不在项目中遍布 wx.request 或 wx.pro.request 这里可以简单进行封装,新建两个文件如下:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/22172.html

// utils/api/fetch.js 封装请求方法、请求拦截器

const app = getApp()

const BaseUrl = 'http://172.0.0.1:7300/mock'

const TokenWhiteList = [
    '/app/user/get-by-code'     // 不需要鉴权的api手动添加到这里
]

/**
 * 设置请求拦截器
 * @param params 请求参数
 */
const fetch = (params = {}) => {
    // 拦截器逻辑
    if (!TokenWhiteList.includes(params.url)) {
        params.header = {
            'content-type': 'application/json',             // 默认值
            'token': app.globalData.token || ''
        }
    }

    if (params.url.startsWith('/')) {    // 拼接完整URL
        params.url = BaseUrl + params.url
    }

    // 返回promise
    return wx.pro.request({ ...params })
      .then(({ data: { code, message, data } }) => {
          // ... 各种异常情况的逻辑处理
          // 与后端约定 code 20000 时正常返回
          if (code === 20000) return Promise.resolve(data)
          return Promise.reject(message)
      })
}

export { fetch }

然后再将所有 API 封装到单独的文件中集中管理:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/22172.html

// utils/api/apis.js 封装所有请求 API

import { fetch } from './fetch'

/* 根据微信code获取用户信息 */
const appUserGetByCode = ({ code } = {}) => fetch({
    url: '/app/user/get-by-code',
    data: { code }
})

/* 扫码登录 */
const appUserQrLogin = ({ qrCode } = {}) => fetch({
    method: 'POST',
    url: '/app/user/qr-login',
    data: { qrCode }
})

/* 个人信息 */
const appUserInfo = () => fetch({
    url: '/app/user/info'
})

/* 系统参数获取,数据字典 */
const appSysParamListByParam = () => fetch({
    url: '/app/sys-param/list-by-param'
})

/* 数据字典所有 */
const appSysParamListAll = () => fetch({
    url: '/app/sys-param/list-all'
})

export {
    appSysParamListAll,   // 数据字典所有
    appSysParamListByParam,   // 系统参数获取,数据字典
    appUserGetByCode,   // 根据微信code获取用户信息
    appUserQrLogin,   // 扫码登录
    appUserInfo   // 个人信息
}

在要使用 API 的地方就可以这样引入:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/22172.html

import * as Api from '../../utils/api/apis.js'   // 相对路径

// 使用方式
Api.appSysParamListAll()
  .then(({ dataList }) => this.upData({ sysParamList: dataList }))
  .then(() => {
      const keyList = this.data.sysParamList.map(T => T.key)
      this.upData({
          keyList,
          formData: { keys: keyList }
      })
  })

使用方式就很舒服,这里使用到了 upData,就是下面我要介绍的内容,是在下非常推介的小程序工具~文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/22172.html

  • 本站内容整理自互联网,仅提供信息存储空间服务,以方便学习之用。如对文章、图片、字体等版权有疑问,请在下方留言,管理员看到后,将第一时间进行处理。
  • 转载请务必保留本文链接:https://www.cainiaoxueyuan.com/xcx/22172.html

Comment

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定