微信小程序> 微信小程序自定义token失效后重新获取token后重新调用接口。

微信小程序自定义token失效后重新获取token后重新调用接口。

浏览量:1730 时间: 来源:beanLau

项目包含app端,小程序端。限制同一个用户无法在多端同时登陆,新登陆会顶掉后登陆的。因为小程序没有退出功能,如果进入页面获取数据时token失效了,无法获取数据,页面显示一片空白,用户体验会很差,所以检测到token失效后重新登陆并重新调用对应api接口。

实现方式:

定义全局变量promiseQueue:[]来保存需要重新获取数据的异步请求参数,exeQueue来判断是否需要循环promiseQueue队列执行队列中的异步请求。

globalData: {    exeQueue: true,    promiseQueue: []}

全局封装的登录接口,调用业务服务器通过code换取token

/**   * 登录校验,获取openid   * successCb 获取用户信息成功回调   */  login: function (successCb) {    let that = this;    wx.login({      success: function (res) {        let requestObj = {          url: "/xxx/login",          method: 'post',          dataobj: {            code: res.code          },        }        wx.showLoading({          title: '努力加载中...',        })        that.promiseRequest(requestObj).then((res) = {          let resData = res.data.data;          if (res.data.code == "000000") { // 成功获取useInfo保存起来。            that.globalData.userInfo = resData;            successCb && successCb()          } else {            wx.hideLoading()            wx.showModal({              title: '提示',              content: res.data.errMsg || '网络错误!',              showCancel: false            })          }        }).catch((errMsg) = {          wx.hideLoading()          console.log(errMsg); //错误提示信息        });        wx.hideLoading()      }    })  },

全局封装的promise接口:

/**   * 封装的promise   * 参数: requestObj 请求成功回调   * throwError: true|false  如果传true则不判断code直接执行requestObj。否则code为100000时提示网络异常   */  promiseRequest: function (requestObj, throwError) {    let that = this;    return new Promise((resolve, reject) = {      //网络请求      wx.request({        url: that.globalData.apiUrl + requestObj.url,        method: requestObj.method,        header: {          ...that.globalData.userInfo,          source: 'wxMini'        },        data: JSON.stringify(requestObj.dataobj),        success: function (res) { //返回取得的数据          let promiseQueue = that.globalData.promiseQueue;          if (res.data.code == '000000' || throwError) {            if (requestObj.resolve){ //如果是promise队列中的请求。              requestObj.resolve(res);              let promiseQueueItem = promiseQueue.shift();              if (that.globalData.exeQueue){ //如果队列可执行则循环队列,保持队列只被循环一次。                that.globalData.exeQueue = false; //防止被多次循环。                while (promiseQueueItem) {                  that.promiseRequest(promiseQueueItem);                  promiseQueueItem = promiseQueue.shift();                  that.globalData.promiseQueue = promiseQueue;                }                if (!promiseQueueItem) {                  that.globalData.exeQueue = true;                  that.globalData.needBeginLogin = true;                }              }            }else{              resolve(res);            }          } else if (res.data.code == '600000' || res.data.code == '700000') { //token失效,重新调用login换取token            requestObj.resolve = resolve;            promiseQueue.push(requestObj); //请求失败了,把该请求放到promise队列,等待更新token后重新调用。            if (!that.globalData.needBeginLogin) { //如果不需要重新登录              return;            }            //防止重复调用login。            that.globalData.needBeginLogin = false;            that.login(() = { //获取完token以后执行回调            //重新登陆以后调用一次队列中的promise;并设置队列为可循环状态。              let promiseQueueItem = promiseQueue.shift();              if (promiseQueueItem) {                that.globalData.exeQueue = true;                that.promiseRequest(promiseQueueItem);                that.globalData.promiseQueue = promiseQueue;              }            }, true)          } else {            wx.hideLoading()            wx.showModal({              title: '提示',              content: res.data.message            })          }        },        error: function (e) {          wx.hideLoading()          reject(e);        }      })    });  }

调用接口

/** 如果调用该接口是状态吗返回60000或70000,则需要重新调用login获取新的token。因为该次请求已失败,会把本次请求参数以及回到放到全局参数promiseQueue中,登录成功后会循环promiseQueue重新发起请求。*/let requestObj = {      url: `/xxx/index`,      method: 'post'    };    wx.showLoading({      title: '努力加载中...',    })    app.promiseRequest(requestObj).then((res) = {      that.setData(res.data.data)      wx.hideLoading()    }).catch((errMsg) = {      wx.hideLoading()      console.log(errMsg);//错误提示信息    });

其他解决方案

上面代码逻辑有点复杂,不过仔细梳理一遍还是能看懂的。如果嫌麻烦可以使用下面方法

that.login(() = { //登录成功回调var page = getCurrentPages().pop(); //获取当前页面实例if (page == undefined || page == null) return; page.onLoad(); //调用实例的onLoad方法重新加载数据;}

当然这样会重新调用页面所有方法,如果有部分接口已经正确返回数据还会重新获取。如果能忍,这个更简单。

版权声明

即速应用倡导尊重与保护知识产权。如发现本站文章存在版权问题,烦请提供版权疑问、身份证明、版权证明、联系方式等发邮件至197452366@qq.com ,我们将及时处理。本站文章仅作分享交流用途,作者观点不等同于即速应用观点。用户与作者的任何交易与本站无关,请知悉。

产品经理

手机 : 13312967497

擅长 : 小程序流量变现

扫码领取礼包

热门模板

  • 头条
  • 搜狐
  • 微博
  • 百家
  • 一点资讯
  • 知乎