这些天团队里开始做小程序开发了, 之前没做过, 都是第一次, 第一次的感觉大家都懂的. 周末看了一下小程序项目的代码, 在网络请求上发现了一些小问题, 最终没忍住想了点办法把 request 封装了一下. 下面来看看吧.
看项目代码时发现了下面几点问题:
网络请求都写在 Page 里, 每个请求都要重复的写 wx.request 以及一些基础配置;
每个页面里都要处理相同类型的异常;
后端返的 http status code 为 200 以外时, 并不能直接进入 fail 对应函数进行处理;
针对这些问题, 首先在项目目录里新建了一个 apis 的目录, 把所有与 API 请求的东西都放在这个目录里, 如下图这样.
apis 目录结构
1. 新建一个 request 类, 对 wx.request 进行简单封装
在 request 类里做了以下几件事:
在构造函数里创建默认请求的 http header, 可以在 header 里配制一些内容, 在对应请求方法中如果没有设置 header 参数, 就使用此默认 header 参数;
以 get post delete put 等方法对 request 进行封装, 在发起网络请求不需要重复的写 wx.request({method:xxx}) 这些代码, 只要调用 getRequest,postRequest 等方法就可以了;
在 rquest 的结果返回处理函数 success 中, 判定服务端返回的状态代码, 对于 200 状态代码的按业务处理成功处理, 对于非 200 的状态码按异常处理.
预留统一异常处理函数处理接口, 可以通过 setErrorHandler 来设置统一的异常处理, 这样对于一些可以统一处理的异常就不用在业务页面里去重复处理了, 例如后端返回 401 的代码, 就可以统一转到登录页面让用户登录了;
此 request 不限定服务提供都, 可以是自己开发的业务服务端, 也可以用于第三方服务的调用;
- /**
- * name: api.js
- * description: request 处理基础类
- * author: 徐磊
- * date: 2018-5-19
- */
- class request {
- constructor() {
- this._header = {}
- }
- /**
- * 设置统一的异常处理
- */
- setErrorHandler(handler) {
- this._errorHandler = handler;
- }
- /**
- * GET 类型的网络请求
- */
- getRequest(url, data, header = this._header) {
- return this.requestAll(url, data, header, 'GET')
- }
- /**
- * DELETE 类型的网络请求
- */
- deleteRequest(url, data, header = this._header) {
- return this.requestAll(url, data, header, 'DELETE')
- }
- /**
- * PUT 类型的网络请求
- */
- putRequest(url, data, header = this._header) {
- return this.requestAll(url, data, header, 'PUT')
- }
- /**
- * POST 类型的网络请求
- */
- postRequest(url, data, header = this._header) {
- return this.requestAll(url, data, header, 'POST')
- }
- /**
- * 网络请求
- */
- requestAll(url, data, header, method) {
- return new Promise((resolve, reject) => {
- wx.request({
- url: url,
- data: data,
- header: header,
- method: method,
- success: (res => {
- if (res.statusCode === 200) {
- //200: 服务端业务处理正常结束
- resolve(res)
- } else {
- // 其它错误, 提示用户错误信息
- if (this._errorHandler != null) {
- // 如果有统一的异常处理, 就先调用统一异常处理函数对异常进行处理
- this._errorHandler(res)
- }
- reject(res)
- }
- }),
- fail: (res => {
- if (this._errorHandler != null) {
- this._errorHandler(res)
- }
- reject(res)
- })
- })
- })
- }
- }
- export default request
2. 新建一个 agriknow 类
在 agriknow 里面做了以下几件事:
实现所有业务服务调用, 如查询所有新闻列表 [getNews] , 查询所有课程列表 [getCourseList] ;
实现统一的异常处理, 并传给 request;
将服务端返回的结果 response 转成 response.data 回传给 API 调用的地方;
- /**
- * name: agriknow.js
- * description: 农知汇服务器提供的服务
- * author: 徐磊
- * date: 2018-5-19
- */
- import request from './request.js'
- class agriknow {
- constructor() {
- this._baseUrl = 'https://apis.xxx.xxx.com/dev/apis/train/v1/'
- this._defaultHeader = { 'data-tupe': 'application/json' }
- this._request = new request
- this._request.setErrorHandler(this.errorHander)
- }
- /**
- * 统一的异常处理方法
- */
- errorHander(res) {
- console.error(res)
- }
- /**
- * 查询所有新闻列表
- */
- getNews(page = 1, size = 10) {
- let data = { page: page, size: size }
- return this._request.getRequest(this._baseUrl + 'news/client', data).then(res => res.data)
- }
- /**
- * 获取所有课程
- */
- getCourseList(page = 1, size = 10, key = null) {
- let data = key != null ? { page: page, size: size, queryValue: key } : { page: page, size: size }
- return this._request.getRequest(this._baseUrl + '/course/mobile', data).then(res => res.data)
- }
- }
- export default agriknow
3. 函数的调用
在 app 中引用 argriknow
- import agriknow from './apis/agriknow.js'
- App({
- onLaunch: function () {
- // 展示本地存储能力
- var logs = wx.getStorageSync('logs') || []
- logs.unshift(Date.now())
- wx.setStorageSync('logs', logs)
- ......
- ......
定义一个类型为 agriknow 的属性并实例化
- import agriknow from './apis/agriknow.js'
- App({
- onLaunch: function () {
- // 展示本地存储能力
- var logs = wx.getStorageSync('logs') || []
- logs.unshift(Date.now())
- wx.setStorageSync('logs', logs)
- ......
- ......
- },
- agriknow:new agriknow()
- })
在 Page 里调用
- const app = getApp();
- Page({
- data: {
- courseData: [],
- page: 1,
- size: 10,
- total: 0
- },
- onLoad: function () {
- ......
- ......
- wx.startPullDownRefresh()
- this.getdataList();
- },
- // 查询课程列表
- getdataList() {
- app.agriknow.getCourseList(this.data.page++, this.data.size, '')
- .then(res => {
- wx.stopPullDownRefresh()
- let list = this.data.page> 2 ? this.data.courseData.concat(res.list) : res.list
- this.setData({
- courseData: list
- })
- })
- .catch(res => {
- wx.stopPullDownRefresh()
- wx.showToast({
- title: '出错了!',
- icon: 'none'
- })
- })
- },
- // 下拉刷新
- onPullDownRefresh() {
- console.log("下拉刷新");
- this.getdataList();
- },
- ......
- ......
- })
所有的东西大概就是这个样子了, 就这么个意思, 希望对大家有点用.
来源: http://www.jianshu.com/p/f9c1d2fde321