微信小程序请求优雅化

1,763 阅读3分钟

前言

小程序原生的wx.request请求代码量繁琐,且容易造成回调地狱,不利于维护。利用Promise封装小程序请求,再封装包裹请求函数reqWrapper全局调用,大大减少代码量,提高可维护性。(注意,以下是以ts编写,可以根据需要改为js)

请求优雅化 VS 原生请求:

 // 优化后的请求,当cgi报错,则默认弹出ret_msg错误字段兜底弹窗
 API.getTest(entryData).then((res: any) => {})
    .catch((err: string) => {
        console.error(err)
 })
 -----------------------------------------------------------------------------------------
 // 原生的请求
 wx.request({
    url: 'test.php', //仅为示例,并非真实的接口地址
    data: {
      x: '',
      y: ''
    },
    method: 'POST',
    success (res: any) {
      console.log(res.data)
    },
    fail (res: any) {
      console.log(res.data)
  })

那么我们需要如何做呢?

一、引入登录态管理的网络请求组件weRequest

公司里一位大佬开发的登录态管理的网络请求组件weRequest,解决繁琐的小程序会话管理,具体可以移步学习。引入后按照文档指引配置request.ts。

let weRequest = require('./weRequest.js');
weRequest.init({
    // [必填] 后端在接口中返回登录成功后的第三方登录态
    getSession: function (res: any) {},
    // [必填] 用code换取session的CGI配置
    codeToSession: {
        // [必填] CGI的URL
        url: ``,
        // [必填] CGI中返回的session值
        success: function (res: any) {}
    },
    // [必填] 触发重新登录的条件,res为CGI返回的数据
    loginTrigger: function (res: any) {
        // 此处例子:当返回数据中的字段errcode等于-1,会自动触发重新登录
    },
    // 登录重试次数,当连续请求登录接口返回失败次数超过这个次数,将不再重试登录
    reLoginLimit: 2,
    // 触发请求成功的条件
    successTrigger: function (res: any) {
        // 此处例子:当返回数据中的字段ret_code等于0时,代表请求成功,其他情况都认为业务逻辑失败
        return res.ret_code == 0;
    },
    // 成功之后返回数据;可不传
    successData: function (res: any) {
        // 此处例子:返回数据中的字段data为业务接受到的数据
        return res;
    },
    // 当CGI返回错误时,弹框提示的标题文字
    errorTitle: function () {
        return '操作失败'
    },
    // 当CGI返回错误时,弹框提示的内容文字
    errorContent: function (res: any) {
        return (res.msg ? res.ret_msg : '操作失败');
    },
    doNotUseQueryString: true
});
export default weRequest

二、封装包裹请求函数

  • 1.引入第一步的配置文件request.ts
import weRequest from '../lib/request'
  • 2.封装包裹函数
/**
 * 包裹函数
 * @param opts weRequest参数
 * @param data 接口参数
 * @param url cgi路径
 * @param reqOpts 请求方式,默认为POST,可选
 */
let reqWrapper = (data: object, url: string, reqLoad?: boolean, reqOpts?: string) => {
    let param = Object.assign({}, data)
    return weRequest.request(Object.assign({}, {
        url: url,
        data: param,
        method: reqOpts? reqOpts : 'POST',
        showLoading: reqLoad? reqLoad : false //当为true时,请求该cgi会有loading       
    }))
}
export default {
    // 把请求export出去,比如
    saveTest(opts: RequestBody.saveTest): Promise<ResponseBody.saveTest> {
        return reqWrapper(opts, url , true)
    },
}

三、自定义报错提示

当我们封装完请求函数后,由于我们在第一步request.ts中,设置了触发请求成功的条件successTrigger,以及默认报错弹窗errorTitle、errorContent。所以一旦我们接口报错了,就会默认触发报错弹窗,我们在catch中也捕获不到err错误,但 weRequest 提供了自定义报错处理的函数fail,我们可以这样封装我们的函数:

/**
 * 包裹函数
 * @param opts weRequest参数
 * @param data 接口参数
 * @param url cgi路径
 * @param reqOpts 请求方式,默认为POST,可选
 * @param faliReport 是否有xxx函数,可选
 */
let reqWrapper = (data: object, url: string, faliReport?: any, reqLoad?: boolean, reqOpts?: string) => {
    let param = Object.assign({}, data)
    return weRequest.request(Object.assign({}, {
        url: url,
        data: param,
        showLoading: reqLoad ? reqLoad : false, //请求过程中是否展示loading
        method: reqOpts ? reqOpts : 'POST',
        fail: faliReport ? function () { faliReport() } : ''
    }))
}

export default {
    // 把请求export出去,比如
    saveTest(opts: RequestBody.saveTest,  faliReport: unknown): Promise<ResponseBody.saveTest> {
        return reqWrapper(opts, url , faliReport)
    },
}

基于上面的封装,我们可以在调用函数的时候,传入我们想自定义报错的xxx函数,这样就可以自定义报错提示了

四、小程序页面中使用

  • 1.在对应的页面引入第二步的文件,比如api.ts
import API from "../../api";
  • 2.请求格式如下
Page({
    data: {},
    onLoad(query: any) {
        this.test()
    },
    test: function () {
        const self = this;
        let entryData: RequestBody = {};
        let testErrorFunction = self. testErrorFunction; //如果需要自定义报错,则传入函数xxx
        API.getTest(entryData, self.testErrorFunction).then((res: any) => {})
        .catch((err: string) => {
            console.error(err)
        })
    },
     //自定义报错xxx函数
    testErrorFunction: function () {
       console.long('error')
    }
})