微信小程序,Token永不过期的Request封装及有登陆页的Request封装--Promise的运用,自动更新小程序新版本及获取导航栏相关信息

十年河东,十年河西,莫欺少钱穷

学无止境,精益求精

个人是个二把手,随笔记录,用于记录学习 ,供以后参考用。

场景:如果无需登录,通过获取用户的基本信息来获取Token,那么,当Token过期时,我们只需重新获取用户基本信息,在拿到Token即可。

          如果有登陆页面,一旦Token过期,我们则跳转到登录页面即可。

系统初始化时,我们将Token赋值为空,过期时间赋值为:1900-01-01

  onLaunch: function (options) {
    let that=this;
    wx.setStorageSync('token', '');
    wx.setStorageSync('tokenOverTime', "1900-01-01");
    that.GetNavigationBarInfo(options);
    that.autoUpdate();
  },

App.JS全部代码如下,主要用于初始化Token值及过期时间,获取系统导航栏相关数据及小程序新版本自动更新

// app.js
App({
  globalData: {
    environment:'dev',// dev uat prd
    statusBarHeight: 0, //状态栏高度
    menuButtonHeight: 0, //胶囊按钮高度 
    navigationBarHeight: 0, //计算得出的导航栏高度
    navigationBarAndStatusBarHeight: 0, //导航栏和状态栏高度之和
    platform: "", //手机型号 android 或 IOS
    isShare:false, //是否由分享而来
  },
  /**
   * 当小程序初始化完成时,会触发 onLaunch(全局只触发一次)
   */
  onLaunch: function (options) {
    let that=this;
    wx.setStorageSync('token', '');
    wx.setStorageSync('tokenOverTime', "1900-01-01");
    that.GetNavigationBarInfo(options);
    that.autoUpdate();
  },

  GetNavigationBarInfo:function(options){
    let that = this;
     // 判断是否由分享进入小程序  从分享进入小程序时 返回上一级按钮不应该存在
     if (options.scene == 1007 || options.scene == 1008) {
      tthathis.globalData.isShare = true;
    } else {
      that.globalData.isShare = false;
    };

    const {
      statusBarHeight,
      platform
    } = wx.getSystemInfoSync();//获取系统信息

    const {
      top,
      height
    } = wx.getMenuButtonBoundingClientRect();

    //console.log(wx.getSystemInfoSync())
    that.globalData.platform=platform;
    //状态栏高度
    that.globalData.statusBarHeight = statusBarHeight;
    // 胶囊按钮高度 一般是32px 如果获取不到就使用32px
    that.globalData.menuButtonHeight = height ? height : 32;
    // 判断胶囊按钮信息是否成功获取
    if (top && top !== 0 && height && height !== 0) {
      // 导航栏高度
      that.globalData.navigationBarHeight = (top - statusBarHeight) * 2 + height
    } else {
      //个别手机获取不到 根据机型进行赋值
      that.globalData.navigationBarHeight = platform === 'android' ? 48 : 40
    }
    //用于绝对定位 占用空间
    that.globalData.navigationBarAndStatusBarHeight= that.globalData.navigationBarHeight+that.globalData.statusBarHeight;
  },

  autoUpdate: function() {
    var self = this
    // 获取小程序更新机制兼容
    if (wx.canIUse('getUpdateManager')) {
      const updateManager = wx.getUpdateManager()
      //1. 检查小程序是否有新版本发布
      updateManager.onCheckForUpdate(function(res) {
        //console.log(res)
        // 请求完新版本信息的回调
        if (res.hasUpdate) {
          //检测到新版本,需要更新,给出提示
          wx.showModal({
            title: '更新提示',
            content: '检测到新版本,是否下载新版本并重启小程序?',
            success: function(res) {
              if (res.confirm) {
                //2. 用户确定下载更新小程序,小程序下载及更新静默进行
                self.downLoadAndUpdate(updateManager)
              } else if (res.cancel) {
                //用户点击取消按钮的处理,如果需要强制更新,则给出二次弹窗,如果不需要,则这里的代码都可以删掉了
                wx.showModal({
                  title: '温馨提示~',
                  content: '本次版本更新涉及到新的功能添加,旧版本无法正常访问的哦~',
                  showCancel:false,//隐藏取消按钮
                  confirmText:"确定更新",//只保留确定更新按钮
                  success: function(res) {
                    if (res.confirm) {
                      //下载新版本,并重新应用
                      self.downLoadAndUpdate(updateManager)
                    }
                  }
                })
              }
            }
          })
        }
      })
    } else {
      // 如果希望用户在最新版本的客户端上体验您的小程序,可以这样子提示
      wx.showModal({
        title: '提示',
        content: '当前微信版本过低,无法使用该功能,请升级到最新微信版本后重试。'
      })
    }
  },
  /**
   * 下载小程序新版本并重启应用
   */
  downLoadAndUpdate: function (updateManager){
    var self=this
    wx.showLoading();
    //静默下载更新小程序新版本
    updateManager.onUpdateReady(function () {
      wx.hideLoading()
      //新的版本已经下载好,调用 applyUpdate 应用新版本并重启
      updateManager.applyUpdate()
    })
    updateManager.onUpdateFailed(function () {
      // 新的版本下载失败
      wx.showModal({
        title: '已经有新版本了哟~',
        content: '新版本已经上线啦~,请您删除当前小程序,重新搜索打开哟~',
      })
    })
  },
})
View Code

首先,我们看下无登录页面的封装【我这里模拟获取Token的信息是使用用户名及密码的方式,真正的无登录场景时,获取Token一般会使用用户基本信息及openID】。

import * as common from "../../utils/config/config"
const ApiUrl = common.config.swagger.apiUrl;
var dayjs = require('dayjs')
export const request = (parm) => {
  let tokenOverTime = wx.getStorageSync('tokenOverTime');
  let bol = dayjs().isBefore(dayjs(tokenOverTime));
  if (!bol) {
    return new Promise((resolve, reject) => {
      wx.request({
        url: ApiUrl + '/Api/V1/Login/UserLogin', //获取Token的接口
        data: {
          "userName": "admin",
          "userPwd": "123456"
        },
        method: "POST",
        header: {
          'content-type': 'application/json' // 默认值
        },
        success(res) {
          if (res.statusCode == 200 && res.data&&res.data.data && res.data.data.token) {
            let newToken = 'Bearer ' + res.data.data.token;
            // //假设我们的Token过期时间时120分钟,留一分钟的余地
            let newTokenOverTime = dayjs().add(119, 'minute').format("YYYY-MM-DD HH:mm:ss"); //假设我们的Token过期时间时120分钟,留一分钟的余地
            wx.setStorageSync('token', newToken);
            wx.setStorageSync('tokenOverTime', newTokenOverTime);

            resolve(res.data);
          } else {
            reject(res.data)
          }
        }
      })
    }).then(A => {
      return new Promise((resolve, reject) => {
        let token = wx.getStorageSync('token');
        parm.header = {
          "Authorization": token
        };
        parm.url = ApiUrl + parm.url;
        wx.request({
          ...parm, // 展开对象 
          success(res) {
            if (res.statusCode == 200 && res.data && res.data.resultCode == 0) {
              resolve(res.data);
            } else if (res.statusCode == 200 && res.data && res.data.resultCode == -1) {
              wx.showModal({
                title: '系统异常',
                content: res.data.resultMessage,
                cancel: false
              })
              reject(res.data);  
            }
            else if (res.statusCode >= 500 && res.statusCode < 600) {
              wx.showModal({
                title: '系统错误',
                content: '网络请求错误',
                cancel: false
              })  
              reject(res.data);  
            } 
            else {
              reject(res.data);
            }
          }
        })
      })
    })
  } else {
    let token = wx.getStorageSync('token');
    return new Promise((resolve, reject) => {
      parm.header = {
        "Authorization": token
      };
      parm.url = ApiUrl + parm.url;
      wx.request({
        ...parm, // 展开对象 
        success(res) {
          if (res.statusCode == 200 && res.data && res.data.resultCode == 0) {
            resolve(res.data);
          } else if (res.statusCode == 200 && res.data && res.data.resultCode == -1) {
            wx.showModal({
              title: '系统异常',
              content: res.data.resultMessage,
              cancel: false
            })
            reject(res.data);
          }
          else if (res.statusCode >= 500 && res.statusCode < 600) {
            wx.showModal({
              title: '系统错误',
              content: '网络请求错误',
              cancel: false
            })
            reject(res.data);  
          } 
          else {
            reject(res.data);
          }
        }
      })
    })
  }
}

注释如下:

import * as common from "../../utils/config/config"
const ApiUrl = common.config.swagger.apiUrl;

主要获取请求的Url,及Api的基础网址。

var dayjs = require('dayjs')

dayJs 主要用于处理时间。

 wx.request({
        url: ApiUrl + '/Api/V1/Login/UserLogin', //获取Token的接口
        data: {
          "userName": "user",
          "userPwd": "123456"
        },

获取Token的接口,在无登录页面小程序中,一般都是先获取用户基本信息,OpenId后,再通过传递这些信息获取Token。

整个Request 返回 ProMise对象,因此,在调用时,我们只需用Then方法接收返回的结果即可

调用如下:

  getdata() {
    let that = this;
    let search = {
      "pageNumber": 1,
      "pageSize": 10
    }
    request.request({
      url: "/api/V2/Finance/SearchFinanceGroupInfo",
      data: search,
      method: "POST"
    }).then(result => {
      console.log(result);
    });
  }

以上便是无登录页的封装及调用。

2、有登陆页面的封装就很简单了,一旦Token过期,则直接跳转至登录页,如下:

import * as common from "../../utils/config/config"
const ApiUrl = common.config.swagger.apiUrl;
var dayjs = require('dayjs')
export const request = (parm) => {
  let tokenOverTime = wx.getStorageSync('tokenOverTime');
  let bol = dayjs().isBefore(dayjs(tokenOverTime));
  if (!bol) {
    //Token过期,跳转至登录页
    return new Promise((resolve, reject) => {
      resolve("tokenTimeOut")
      wx.showModal({
        title: '提示',
        content: '登录超时,请重新登录',
        showCancel: false,
        success: function (res) {
          if (res.confirm) {
            wx.reLaunch({
              url: '/pages/login/account/account',
            })
          }
        }
      })

    }).catch(value => {
      console.log(value);
    })
  } else {
    let token = wx.getStorageSync('token');
    return new Promise((resolve, reject) => {
      parm.header = {
        "Authorization": token
      };
      parm.url = ApiUrl + parm.url;
      wx.request({
        ...parm, // 展开对象 
        success(res) {
          if (res.statusCode == 200 && res.data && res.data.resultCode == 0) {
            resolve(res.data);
          } else if (res.statusCode == 200 && res.data && res.data.resultCode == -1) {
            wx.showModal({
              title: '系统异常',
              content: res.data.resultMessage,
              cancel: false
            })
            reject(res.data);
          } else if (res.statusCode >= 500 && res.statusCode < 600) {
            wx.showModal({
              title: '系统错误',
              content: '网络请求错误',
              cancel: false
            })
            reject(res.data);
          } else {
            reject(res.data);
          }
        }
      })
    })
  }
}

附注,config.js 如下:

var app = getApp();
export let config = new class {
  constructor() {
    if (app.globalData.environment == "prd") {
      this.swagger = {
        imgUrl: 'https://xxx.com/images/user/', // 图片-正式服务器
        apiUrl: 'https://xxx.com/pingtaiBackend',
      }
    } else if (app.globalData.environment == "uat") {
      this.swagger = {
        imgUrl: 'https://xxx.com/SIT/images/user/', // 图片-UAT服务器
         apiUrl: 'https://xxx.com/SIT/pingtaiBackend',
      }
    } else {
      this.swagger = {
        imgUrl: 'https://xxx.com/DEV/images/user/', // 图片-测试服务器
        apiUrl: 'https://xxx.com/DEV/pingtaiBackend'
      }
    }
  }
  swagger = {
  }
};

没什么好说了,要想看的懂,必须熟练ES6 / Promise的使用及DayJS,小程序开发组件库。

@天才卧龙的博客

 

posted @ 2021-12-09 11:54  天才卧龙  阅读(772)  评论(0编辑  收藏  举报