微信小程序http网络请求封装,支持Promise,支持自动携带token,支持认证失败重连

蛰伏已久 蛰伏已久 2018-03-27

微信小程序原生的网络请求we.request,存在以下几个问题

  • 当发生多层网络请求嵌套时,代码结构很差,需要改写成promise形式

  • 有的接口需要用户登录,即携带token(用户登录成功后,后台返回的token,存储在小程序中)才能进行访问,否则会返回认证失败,所以要解决2个问题,1是自动携带token,2是认证失败最好重新登录重新进行访问

  • 网络请求经常用到,现在的写法很多都是重复的

所以我们必须对网络请求进行封装。

封装的请求流程大致如下

  • 检查是否有网络,无网络提醒稍候重试

  • 如果有网络发起请求,请求时携带token到header的Authorization中

  • 如果返回数据code==1001(认证失败的错误码,根据自己情况改写),则重新进行登录操作

    a. 调用wx.login获取code

    b.调用后台的login接口,登录成功返回token

    c.将token存储到本地

    d.再次发起网络请求

  • 如果返回数据code==1(成功),调用成功回调

  • 其他情况 调用失败回调


源码如下,其中所有的小程序接口均已改成promise形式,见 http://shanhuxueyuan.com/news/detail/23.html

//network.js

var wxapi = require("../network/base.js").wxapi;
var api=require("../network/config.js").api;


const method={
  post: "POST",
  get: "GET"
}

function fetch({ url, data = '', method='POST'}){ 
  return new Promise((resole,reject)=>{
    wxapi("getNetworkType")
    .then(res=>{
      if (res.networkType=="none"){
            wx.showToast({
              title: '网络好像不太好哦,请稍候再试',
              icon: "none"
            })
      }else{
        wxapi("request", {
          url: api.base_url + url,
          header: {
            'Authorization': 'Bearer ' + wx.getStorageSync('token'),
            'content-type': 'application/x-www-form-urlencoded' // 默认值
          },
          data: data,
          method: method,
        })
          .then(res => {
            if (res.data.code == 1001) {
              //认证失败,重新登录
              wx.showToast({
                title: '验证失败,自动重试',
                icon:"none"

              })
              wxapi("removeStorage", { key: "token" })
                .then(() => wxapi("login"))
                .then(res => fetch({
                  url: api.login,
                  data: {
                    code: res.code
                  },
                })
                )
                .then(res => {
                  if (res.code == 1) {
                    //登录成功,重新请求一次
                    wx.setStorageSync('token', res.data.token)
                    wxapi("request", {
                      url: api.base_url + url,
                      header: {
                        'Authorization': 'Bearer ' + wx.getStorageSync('token'),
                        'content-type': 'application/x-www-form-urlencoded' // 默认值
                      },
                      data: data,
                      method: 'POST',
                    })
                      .then(res => {
                        if (res.data.code == 1) {
                          resole(res.data)
                        } else {
                          reject(res.data)
                        }
                      })
                  }
                })
            } else if (res.data.code == 1) {
              //成功
              resole(res.data)
            } else {
              //失败
              reject(res.data)
            }
          }).catch(res => {
            reject(res.data)
          })
      }
    })
      
  })
}

module.exports = {fetch, method}

在页面中调用

var network=require("../../utils/network/network.js")
var wxapi = require("../../utils/network/base.js").wxapi;
var api = require("../../utils/network/config.js").api;

Page({

  onLoad: function () {
  
      network.fetch({
         url: api.course_detail,
         data: {
             id: 18
         },
      })
      .then(res=>{
        console.log(res);
      })
      .catch(res=>console.log(res))
      },
  
  }

})


接口地址,放在config.js中

const api={
  base_url: 'https://****.com',
  login: '/v1/user/login',
  course_detail: '/v1/course/detail',
}

module.exports={api}


base.js 将微信的api封装成promise形式

function wxapi(function_name, obj) {
  return new Promise((resole, reject)=>{
    wx[function_name]({
      ...obj,
      success: res => resole(res),
      faile:res=>reject(res)
    })
  })
}



module.exports = {wxapi}


分享到

点赞(7)