mpvue+vuex封装wx.request管理token

一开始网上查资料看到mpvue中封装wx.request返回promise对象,感觉这样就够用了,也就没有用axios、flyio等库,后面需要结合token管理的时候就比较苦逼了,接下来的内容跟axios、flyio等内容完全不搭边,flyio等如果想管理token的话,需要做请求拦截,具体可以自行百度。

一、封装wx.request

在src/utils目录下新建requestMethod.js文件进行请求封装,可以新建config.js文件作为配置文件,存放请求基地址。

config.js:

const baseUrl = 'https://www.zwl.com/api/v1'

export default{
  baseUrl
}

在使用的时候调用get方法,会在return处执行request(),request会返回一个Promise实例,在Promise实例化的时候发送了请求,requestMethod.js:

import Config from './config'

function request (url, method, data, header = {}) {
  wx.showLoading({
    title: '加载中' //  数据请求前loading
  })
  return new Promise((resolve, reject) => {
    wx.request({
      url: Config.baseUrl + url,
      method: method,
      data: data,
      header: {
        'content-type': 'application/json'
      },
      success: function (res) {
        wx.hideLoading()
        resolve(res.data)
      },
      fail: function (error) {
        wx.hideLoading()
        reject(error)
      },
      complete: function () {
        wx.hideLoading()
      }
    })
  })
}
function get (obj) {
  return request(obj.url, 'GET', obj.data)
}
function post (obj) {
  return request(obj.url, 'POST', obj.data)
}

export default {
  request,
  get,
  post
}

使用前需要将封装的请求挂在Vue原型上,被所有vue实例共享(相当于定义了全局变量,在.vue文件中可以直接使用)。src/main.js如下:

import Vue from 'vue'
import App from './App'
import request from './utils/requestMethod'

// 将request赋值给Vue原型链上的$http属性($http属性将被创建)
Vue.prototype.$http = request
Vue.config.productionTip = false
App.mpType = 'app'

const app = new Vue(App)
app.$mount()

在src/pages/index/index.vue中使用如下:

<template>
  <div></div>
</template>
<script>

export default {
  data () {
    return {
      dataList: []
    }
  },
  methods: {
    //  初始化数据
    initData () {
      this.$http.post({
        url: '/collection/is_collect/',
        data: {'id': 7}
      }).then((res) => {
        //    请求成功执行回调,开始初始化数据
        this.dataList = res.data
        
      })
    }
  },
  created () {
    //    在vue实例创建时执行数据初始化
    this.initData()
  }
}
</script>

<style lang="stylus" rel="stylesheet/stylus">

</style>

二、vuex管理token

在src下新建目录store,store目录如下:

把要管理的数据放入state.js文件:

const state = {
  token: ''
}

export default state

在mutation-types.js中定义类型(想不到词形容这个文件的作用,直接看操作吧):

//    设置token
export const SET_TOKEN = 'SET_TOKEN'
//    更新token
export const UPDATE_TOKEN = 'UPDATE_TOKEN'

在mutations.js文件中对数据进行操作,这里我们同时把token存入本地缓存:

import * as types from './mutation-types'

const matations = {
  /**
   * state: 当前状态树
   * v: 提交matations时传的参数
   * 设置token时执行的操作
   */
  [types.SET_TOKEN] (state, v) {
    state.token = v
    //  同步存入本地缓存
    wx.setStorageSync('token', v)
  },
  //  更新token时执行的操作  
  [types.UPDATE_TOKEN] (state, v) {
    state.token = v
    wx.setStorageSync('token', v)
  }
}

export default matations

 在src/store/index.js中进行组装:

import Vue from 'vue'
import Vuex from 'vuex'

import state from './state'
import getters from './getters'
import actions from './actions'
import mutations from './mutations'

Vue.use(Vuex)

export default new Vuex.Store({
  state,
  getters,
  actions,
  mutations
})

在src/main.js中将store挂在原型上:

import store from './store/index'

Vue.prototype.$store = store

使用示例:

//   注意‘UPDATE_TOKEN’将执行mutations下的[types.UPDATE_TOKEN]对应的操作

this.$store.commit('UPDATE_TOKEN', token的新值) 

三、携带token访问API

以下是根据个人开发的小程序里设计的token管理流程

根据流程图,主要是在访问API后对返回的状态进行判断,是否出现token过期或者token为空的状态,然后重新获取token,再重发当前请求。首先,封装一个方法用作从服务器获取token,src/utils/token.js:

import Config from './config'

//  从服务器获取token
function getTokenFromServer () {
  return new Promise((resolve, reject) => {
    wx.login({
      success: function (res) {
        wx.request({
          url: Config.baseUrl + '/token/user',
          method: 'POST',
          data: {
            code: res.code
          },
          success: function (res) {
            //    取得token后需要对现在的token进行更新
            this.$store.commit('UPDATE_TOKEN', res.data.token)
            resolve(res.data)
          }
        })
      }
    })
  })
}

这里可能会出现错误说$store undefined;

这里可能原因是this的指向问题,这里的this指向是当前js文件,所以需要想办法引入vue实例,vue实例可以使用$store变量: 

之后需要重写之前封装的请求,requestMethod.js: 

四、全部代码:

 requestMethod.js:

import Config from './config'
import Token from './token'

function request (url, method, data, header = {}, noRefetch = false) {
  wx.showLoading({
    title: '加载中' //  数据请求前loading
  })
  return new Promise((resolve, reject) => {
    wx.request({
      url: Config.baseUrl + url,
      method: method,
      data: data,
      header: {
        'token': wx.getStorageSync('token'),
        'content-type': 'application/json'
      },
      success: function (res) {
        wx.hideLoading()
        let code = res.statusCode.toString()
        let startChar = code.charAt(0)
        if (startChar === '2') {
          resolve(res.data)
        } else {
          if (code === '401') {
            if (!noRefetch) {
              Token.getTokenFromServer().then((token) => {
                //  获取token之后重新发送请求
                request(url, method, data, {}, true).then((res) => {
                  resolve(res)
                })
              })
            }
          }
        }
      },
      fail: function (error) {
        wx.hideLoading()
        reject(error)
      },
      complete: function () {
        wx.hideLoading()
      }
    })
  })
}
function get (obj) {
  return request(obj.url, 'GET', obj.data)
}
function post (obj) {
  return request(obj.url, 'POST', obj.data)
}

export default {
  request,
  get,
  post
}

token.js:

import Config from './config'
import Vue from 'vue'

let vue = new Vue()

function verify () {
  let token = wx.getStorageSync('token')
  if (!token) {
    // 不存在token缓存,获取token
    getTokenFromServer()
  } else {
    // 对缓存中的token进行验证
    verifyFromServer(token)
  }
}

//  从服务器获取token
function getTokenFromServer () {
  return new Promise((resolve, reject) => {
    wx.login({
      success: function (res) {
        wx.request({
          url: Config.baseUrl + '/token/user',
          method: 'POST',
          data: {
            code: res.code
          },
          success: function (res) {
            vue.$store.commit('UPDATE_TOKEN', res.data.token)
            resolve(res.data.token)
          }
        })
      }
    })
  })
}

// 携带令牌去服务器校验
function verifyFromServer (token) {
  wx.request({
    url: Config.baseUrl + '/token/user',
    method: 'POST',
    data: {
      token: token
    },
    success: function (res) {
      let valid = res.data.isValid
      if (!valid) {
        getTokenFromServer()
      }
    }
  })
}

export default{
  verify,
  getTokenFromServer,
  verifyFromServer
}

main.js:

import Vue from 'vue'
import App from './App'
import request from './utils/requestMethod'
import store from './store/index'

Vue.prototype.$store = store
Vue.prototype.$http = request
Vue.config.productionTip = false
App.mpType = 'app'

const app = new Vue(App)
app.$mount()

使用时,如果当前token无效可以在调试的时候看到当前网络请求发送了两次,第一次为401,第二次为成功状态:

<template>
  <div></div>
</template>
<script>

export default {
  data () {
    return {
      dataList: []
    }
  },
  methods: {
    //  初始化数据
    initData () {
      this.$http.post({
        url: '/collection/is_collect/',
        data: {'id': 7}
      }).then((res) => {
        //    请求成功执行回调,开始初始化数据
        this.dataList = res.data
        
      })
    }
  },
  created () {
    //    在vue实例创建时执行数据初始化
    this.initData()
  }
}
</script>

<style lang="stylus" rel="stylesheet/stylus">

</style>

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值