Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

浅谈小程序中的请求封装 #8

Open
KarthusLorin opened this issue Jun 26, 2020 · 0 comments
Open

浅谈小程序中的请求封装 #8

KarthusLorin opened this issue Jun 26, 2020 · 0 comments

Comments

@KarthusLorin
Copy link
Owner

浅谈小程序中的请求封装

近两个月学习了小程序的开发,并且撸了一个不大不小的demo,算是正式入门了小程序,在此想分享下小程序的开发经验。

前言

在小程序的开发中,或者说在整个前端开发中,请求都是绕不过去的一道坎。在Vue开发中,我们可以采用 axios 这个成熟的插件来进行HTTP请求。但是,遗憾的是,到目前为止,小程序没有一个比较好用的插件来进行HTTP请求。此时,我们需要对小程序的HTTP请求进行封装,以方便我们后续开发。

浅析wx.request

众所周知,在小程序中,我们通过 wx.request 方法来进行HTTP请求(或者说是HTTPS请求)。

通过 官方文档 我们可以知道, wx.request 方法接收一个对象,对象可以有9个属性:urldataheadermethoddataTyperesponseTypesuccessfailcomplete。除了url是必填的以外,其余都是可选项。在这些属性里面,最常用的是 methoddataheadersuccess以及fail这几个属性。毕竟我们总要设置请求方法、请求数据、请求头以及请求成功或失败的处理方法是不是?

所以接下来我们的目标我们已经明确,就是对这些常用属性进行封装。

封装HTTP类

对于HTTP请求的封装,有很多种方法,比如:axios 采用的是通过IIFE作为工厂函数处理并返回一个Axios的实例。在这里,我推荐使用类,因为类的封装形式,正是axios 的封装形式的加强版。

为了一致性,我也采用request作为请求的方法名,并且接受相同的对象作为参数。此时,我们已经可以实现出以下代码:

class HTTP {
    request (params) {
        wx.request({
            url: params.url,
            method: params.method,
            data: params.data,
            header: params.header,
            success: (res) => {
                params.success(res)
            },
            fail: (err) => {
                params.fail(err)
            }
        })
    }
}

接下来,我们需要对各个属性进行处理。

缺省属性处理

由于除了url,其余的的属性皆为可选可选项,所以需要对可选属性进行缺省属性的处理。

在小程序官方文档中,当不传入method属性时,默认采用GET方法,所以我们需要将method的默认值设为GET,设置method的默认值的方式很简单:

if (!params.method) {
	params.method = 'GET'
}

但是,这种方式不够优雅,我们可以采用位运算符的方式进行默认复制:

...
method: params.method || 'GET'
...

其余属性也采用类似方式进行缺省值处理,除了successfail属性,这个我们后面说。

从配置文件中导入HTTP参数

在正常情况下,REST风格的接口协议给的接口路径都是诸如/pathA/a,在此之前还有一个类似于www.baidu.com/root类似的base url,两者结合才是真正的请求路径。在Vue中,我们可以通过webpack中的proxyTable来解决这个问题,但是,小程序中没有webpack中的proxyTable,所以需要每次请求的时候,都输入完整请求路径。

在HTTP类中的request方法,我们可以实现路径的拼接。

...
url: 'www.baidu.com/root' + params.url,
...

但是,这里有个问题,base url是写死的,也就是说,我们每做一个项目,都需要重新设置一次base url的值,这显然是有问题的。

为了处理该问题,我新建了一个config.js文件,作为该项目的配置文件,用来存储所有项目相关的配置,比如base url以及HTTP Header。

const config = {
  api_base_url: 'www.baidu.com/root'
  // 更多的配置项
}

export {config}

拥有配置文件最大的好处就是,每次修改项目,只需要修改配置文件中的配置项的值即可,重复保证了组件的封闭性,减少了对项目的耦合。

封装success

最后,我们需要封装success以及fail

显而易见,我们只有在HTTP状态码为2**或者304才调用success,所以我们需要对响应结果的状态码进行判断,根据判断结果决定是否执行params.success

...
success: (res) => {
    let code = res.statusCode.toString()
    // 状态码判断
    if (code.startsWith('2') || code === '304') {
        params.success && params.success(res.data)
    } else {
        // 失败
    }
}

tips:一般情况下,我们还可以对显示错误的方法进行一次封装,调用wx.showToast显示服务器返回的错误信息。

全部代码

经过这么多步骤,封装结束后的代码是:

import {config} from '../config.js'

class HTTP {
  request (params) {
    wx.request({
      url: config.api_base_url + params.url,
      method: params.method || 'GET',
      data: params.data || {},
      header: params.header ? Object.asign(config.header, params.header):config.header
      success: (res) => {
        let code = res.statusCode.toString()
        if (code.startsWith('2') || code === '304') {
          params.success && params.success(res.data)
        } else {
          params.fail && params.fail(res.data)
          let error_code = res.data.error_code
          this._show_error(error_code)
        }
      },
      fail: (err) => {
        params.fail && params.fail(res.data)
        this._show_error(1)
      }
    })
  }
    
  // 私有方法,显示请求错误信息
  _show_error(error_code) {
    if (!error_code) {
      error_code = 1
    }
    const tip = config.tips[error_code]
    wx.showToast({
      title: tip ? tip : tips[1],
      icon: 'none',
      duration: 2000
    })
  }
}

其实,HTTP类还可以进一步优化,比如,使用解构以及默认赋值,使用promise等等,篇幅有限,我就不一一细说了,详情可以查看我github上的代码。

代码路径:https://github.com/KarthusLorin/mini-program/blob/master/util/http.js

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant