Code前端首页关于Code前端联系我们

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

terry 2年前 (2023-09-22) 阅读数 76 #移动小程序

2.1 使用成品库

安装promise库wx-promise-pro。记得带上-s--生产,否则构建不会成功。

npm i -S wx-promise-pro

然后在app.js

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

promisifyAll()  // promisify all wx api

App({ ... })

然后就可以正常使用了:

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

2.2 自己实现

其实我们可以自己实现这样一个库。原理很简单,以原生 API 的 wx.request 为例:

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

如果我们让它成为一个 Promise,那么调用方法应该是:

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

And then 该函数给出了一个 Promise -return object ,所以这个函数可以调用链继续下去,所以我们首先需要 new 来获取一个 Promise 对象:

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

我们可以进一步改进这段代码,因为 Success fail此处输入参数仅使用resolvereject方法执行,因此它们会立即ve。reject 方法就够了。

另外,由于其他小程序的原生 API 格式是一样的,所以我们可以使用 curry 方法来处理其他需要 Promise 的 API:

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

那么 curry 的结果就是 -method as new 的 Promise基于 的 API 挂载在 wx.pro 对象上:

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

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

然后为了方便我们使用其他方法,我们可以通过基于对象的 wx 方法来释放 Promise,比如 请求扫描代码显示Toast❀、er等。被一个接一个地安装。 wx.pro对象,可以直接使用wx.pro.xx。由于此方法返回一个 Promise 对象,因此可以像任何其他 Promise 对象一样使用它。

其实在不知不觉中,我们实现了wx-promise-pro的源代码。这个库的核心代码就是上面几行?

2.3 项目中使用

有了上面的工具我们就可以在项目中使用了。为了不将它们分散到整个项目中wx.requestwx.pro.request这里我们可以简单地封装它们并创建两个新的。文件如下:

// 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封装在单独的文件中,集中管理:

// 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​​,你可以这样想象:

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,这是我下面介绍的一个我强烈推荐的小程序工具~

版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门