小程序request的封装

wx.request 的封装

小程序提供了request的网络接口,用于服务器交互。但是我们在开发的过程中发现了以下问题:

  • 每个页面中都要去写一些重复的相关配置,比如header
  • 没有统一的loading提示管理
  • 没有统一的错误处理机制
  • 页面逻辑与请求服务器代码混在一起,比较混乱,不好调试

统一header问题

发起请求时,服务器有些接口需要验证用户身份,一般是会把用户登录之后的token设置在header中,回传给服务器,我们可以写一个通用的方法:

/**
 * 获取header
 */
function getCommonHeader() {

  let header = {
    'Content-type': 'application/x-www-form-urlencoded'
  };

  // 如果token有值则带上
  let token = wx.getStorageSync("token");
  if (token) {
    header = Object.assign({}, header, {
      'Authorization': 'Bearer ' + token
    });
  }

  return header;
};

统一loading管理

为了防止用户多次点击以及更好的用户体验,一般发起请求时会加上loading动画,服务器返回之后再去掉这个loading。但是产品设计时也有不加loading动画和自定义loading文字的需求,所以我们可以添加一个控制开关 showLoadingloadingTitle ,由外部调用时设置。

统一错误处理机制

这里需要和服务器约定统一返回结果格式,比如:

{"code": 0, "data": "", "msg": "ok"}

解释一下:

  • code 表示本次请求的状态码
  • data 是服务器返回的数据
  • msg 业务错误提示

首先对此次请求的http状态判断,非 200 则表示此次请求失败了,可能是 500 服务器报错,也可能是 404 请求服务器url未找到等等。
接着对业务状态判断,这个由服务器约定,比如 0 表示成功,非 0 则表示业务错误,一般直接 toast 提示服务器返回的 msg 就可以了,这样就对服务器错误进行了统一处理。
但是和 loading 一样,有些页面需要有特殊的错误处理,这时我们也添加一个控制开关 showToast ,由调用时控制是否显示统一的错误信息。

接口promise化

为了调用时少些回调,我们把这个request接口包装成一个promise,调用时直接使用 thencatch 来处理业务。最终的代码如下:


/**
 * 网络请求
 */
function request(url, data = {}, header = {}, method = "POST", config = {}) {

  // header 空值处理
  let _header = {
    "content-type": "application/x-www-form-urlencoded"
  };
  if (Object.keys(header).length > 0) {
    _header = header;
  }

  let showToast = true,
    showLoading = false,
    loadingTitle = "加载中。。。";
  // 默认显示toast
  if (config['showToast'] != undefined && config['showToast'] == false) {
    showToast = false;
  }
  // 默认显示loading
  if (config['showLoading'] != undefined && config['showLoading'] == true) {
    showLoading = true;
  }
  if (config['loadingTitle']) {
    loadingTitle = config['loadingTitle'];
  }

  return new Promise((resolve, reject) => {
    // 是否显示loading
    if (showLoading) {
      wx.showLoading({ title: loadingTitle, icon: 'none', mask: true });
    }

    wx.request({
      url: url,
      data: data,
      header: _header,
      method: method,
      success: (res => {
        if (showLoading) {
          wx.hideLoading();
        }

        // 服务器 非200 错误
        if (res.statusCode && res.statusCode != 200) {
          wx.showToast({ title: '服务器 ' + res.statusCode + ' 错误', icon: 'none' });
          reject(res);
          return;
        }

        if (res.data && res.data.code != 0) {
          // 业务状态非0 是否提示
          if (showToast) {
            wx.showToast({ title: res.data.msg, icon: 'none' });
          }

          reject(res);
          return;
        }
        resolve(res.data);
      }),
      fail: (err => {
        if (showLoading) {
          wx.hideLoading();
        }

        if (err.errMsg.indexOf('url not in domain list') > -1) {
          wx.showToast({ title: '请求url不在合法域名中,请打开调试模式', icon: 'none' });
        }

        reject(err);
      })
    });
  });

};

对于 get 请求和 post 请求我们再包装一下


/**
 * get 网络请求
 */
function getRequest(url, data = {}, header = {}, config = {}){
  return request(url, data, "GET", header, config);
}

/**
 * post 网络请求
 */
function postRequest(url, data = {}, header = {}, config = {}){
  return request(url, data, "POST", header, config);
}

我们看看调用的例子,将上面封装好的request函数放到 utils.js里面,新建一个api.js文件:

const utils = require('../utils.js');

module.exports = {
  getUserInfo: function(data, config = {}){
    return utils.postRequest(
      'http://api.xx.com/get_user_info',
      data,
      utils.getCommonHeaders(),
      config
    );
  }
}

然后页面调用:

const api = require('../api.js');
/**
 * 生命周期函数--监听页面加载
 */
onLoad: function (options) {
  api.getUserInfo({
      "user_id": "1"
    }, {
      "showLoading": "false",
      "showToast": "false",
      "loadingTitle": "登录中"
    })
    .then(res => {
      console.log(res);
    });
}

一般情况下上面的 showLoading 参数等配置项可以不写,用默认就行,那页面就更简洁了

const api = require('../api.js');

api.getUserInfo({"user_id": "1"})
  .then(res => {
    console.log(res);
  });
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容