uniapp登录成功后跳回原有页面+无感刷新token

uniapp登录成功后跳回原有页面

引言

在C端的页面场景中,我们经常会有几种情况到登录页:

  • 区分需要登录和不用登录的页面,点击需要登录才能查看的页面
  • 已经登录但是超时,用户凭证失效等原因

以上情况可以细分为两种,一种是从未登录过的,需要第一次去登录,还一种是已经登录了,但是cookie失效了,需要重新获取用户凭证,这样的话后端会将两个状态码区分,那我们前端需要根据不同的状态码进行相应的处理。

第一次登录时

当用户从未登录时,我们需要跳到登录页去登录后再返回到原有页面,这样才是正常的交互逻辑。

  1. 第一步需要先保存当前路由
javascript 复制代码
 // 记录路由地址
const fungoPreviousPage = () => {
 let routes = getCurrentPages(); // 获取当前打开过的页面路由数组
 let curRoute = routes[routes.length - 1].route //获取当前页面路由
 let curParam = routes[routes.length - 1].options; //获取路由参数
 // 拼接参数
 let param = ''
 for (let key in curParam) {
   if (!param) {
     param += key + '=' + curParam[key]
   } else {
     param += '&' + key + '=' + curParam[key]
   }
 }
 uni.setStorageSync('pageUrl', param ? `/${curRoute}?${param}` : `/${curRoute}`)
}
  1. 登录成功后判断是否有pageUrl,有就说明回到原页面
javascript 复制代码
   var pageUrl = uni.getStorageSync('pageUrl')
   if (pageUrl) {
     // 如果为tabbar页面则用reLaunch跳转
     if (['/pages/home/index'].includes(pageUrl)) {
       uni.reLaunch({url: pageUrl})
     } else {
       uni.redirectTo({url: pageUrl})
     }
     //跳转后,删除url记录避免重复跳转
     uni.removeStorageSync('pageUrl')
   } else {
     // 如果没有默认跳转到首页
     uni.reLaunch({url: '/pages/home/index'})
   }
  1. 回到原页面后点击返回需要返回到上一层页面(排除登录页)

    这点要注意的是整个流程是首页-a-登录页-a,如果在a页面点击返回时是要到首页,则需要注意以下

    a页面跳转到登录页时需要使用uni.redirectTo 跳转,登录页跳转到a页面也需要使用uni.redirectTo

cookie失效

cookie失效了需要无感知更新cookie,这个时候需要先将请求的队列存起来,等刷新cookie再去调用原来的接口就行。

后端一般会在登录成功后返回两个token值,一个用来校验用户信息,一个用来获取新的token,我这边分为token和access_token两个字段,其实就一个时效长一个时效短。

完整代码如下

javascript 复制代码
  let devUrl = '';
  import store from '../store/index.js'
  import { loginOut } from './index.js'

  const baseUrl = devUrl;
  const POST = 'POST';
  const UPLOAD = 'UPLOAD';
  const SUCCESS_CODES = 200;
  const RefreshCode = 777;
  const LogoutCode = 503;
  const TOKEN_ERROR = 444
  const ERRCODE = 500

  let promiseQueue = []
  let exeQueue = false
  let needBeginLogin = true
  // 刷新token
  async function RefreshTokenRQ(cb) {
    try {
      if (store.state.access_token) {
          uni.request({
            url: `${baseUrl}/user/refreshToken`,
            data: {exchangeToken: store.state.access_token},
            success(res) {
              if (res.data.status === SUCCESS_CODES) {
                store.commit('setToken', res.data.data)
                cb && cb()
              } else {
                loginOut()
              }
            }
          })
      } else {
        loginOut()
      }
    } catch (e) {}
  }

  const getHeader = () => {
    return {
      token: store.state.token,
    };
  };
  /**
   *
   * @param {string} method 请求方法
   * @param {string} url api地址
   * @param {string} data 入参
   */
  const request = async (requestObj) => {
    // 显示加载中 效果
    // uni.showLoading({
    // 	title: "",
    // 	mask: true,
    // });
    return new Promise((resolve, reject) => {
      uni.request({
        url: `${baseUrl}${requestObj.url}`,
        method: requestObj.method || 'get',
        data: requestObj.data || {},
        header: Object.assign(getHeader(), requestObj.header || {}),
        success(res) {
          // 请求成功
          const data = res.data;
          requestMethods(requestObj, data, resolve, reject )
        },
        fail(err) {
          console.log(err);
          // 请求失败
          reject(new Error('Por favor verifique a rede'));
        }
      });
    })
  }
  function requestMethods (requestObj, data, resolve, reject) {
    if (data.status === SUCCESS_CODES) {
      if (requestObj.resolve) {
        requestObj.resolve(data.data);
        let promiseQueueItem = promiseQueue.shift();
        if (exeQueue) {
          exeQueue = false;
          while (promiseQueueItem) {
            request(promiseQueueItem);
            promiseQueueItem = promiseQueue.shift();
            promiseQueue = promiseQueue;
          }
          if (!promiseQueueItem) {
            exeQueue = true;
            needBeginLogin = true;
          }
        }
      } else {
        resolve(data.data);
      }
    } else {
      // 其他异常
      if (data.status === RefreshCode) {
        try {
          if (store.state.access_token) {
            requestObj.resolve = resolve;
            promiseQueue.push(requestObj); //请求失败了,把该请求放到promise队列,等待更新token后重新调用。
            if (!needBeginLogin) {
              return;
            }
            //防止重复刷新token。
            needBeginLogin = false;
            RefreshTokenRQ(() => { //获取完token以后执行回调
              //重新登陆以后调用一次队列中的promise;并设置队列为可循环状态。
              let promiseQueueItem = promiseQueue.shift();
              if (promiseQueueItem) {
                exeQueue = true;
                request(promiseQueueItem);
              }
            }, true)
          } else {
            loginOut()
          }
        } catch (e) {}
        return
      } else if (data.status === LogoutCode || data.status === TOKEN_ERROR) {
        loginOut()
        return;
      } else {
        uni.showToast({
          title: data.message,
          icon: 'none'
        });
      }
      reject(data);
    }
  }

  export function get(url, data, header = {}, method = 'GET') {
    return request({
      url,
      data,
      header
    })
  }

  export function post(url, data, header = {}, method = 'POST') {
    return request({
      url,
      data,
      method,
      header
    })
  }
  export default{
    get,post
  };

以上loginOut和store根据自己实际情况调整

相关推荐
_处女座程序员的日常8 小时前
Rollup failed to resolve import “destr“ from ***/node_modules/pinia-plugin-pers
javascript·uni-app·vue
慢慢雨夜16 小时前
uniapp打包华为,提示请提供64位版本软件包后再提交审核
uni-app
秋雨凉人心17 小时前
uniapp 设置安全区域
前端·javascript·vue.js·uni-app
Little_Code17 小时前
uniapp 如何使用vuex store (亲测)
uni-app·vuex·store
咸虾米_17 小时前
uniCloud云对象调用第三方接口,根据IP获取用户归属地的免费API接口,亲测可用
网络·uni-app·unicloud
Jiaberrr20 小时前
uniapp中使用原生ajax上传文件并携带其他数据,实时展示上传进度
前端·javascript·vue.js·ajax·uni-app
上趣工作室1 天前
uniapp中使用全局样式文件引入的三种方式
开发语言·rust·uni-app
秋田君1 天前
uniapp路由与页面跳转详解:API调用与Navigator组件实战
uni-app
FIRE1 天前
uniapp小程序分享使用canvas自定义绘制 vue3
前端·小程序·uni-app
@Carey2 天前
uniapp配置消息推送unipush 厂商推送设置配置 FCM 教程
uni-app