在 uni-app 中解决用户异步登录渲染问题

438 阅读1分钟

小程序登录

基于openid的登录流程,微信小程序在用户进入时会使用 wx.login 获取 authcode 达到自动登录的目的。

小程序登录时序图.jpg

小程序端简单示例:

// 该方法进入小程序时会尝试调用,自动登录
async function userLogin() {
    wx.login({
        async success(res) {
            if (res.code) {
                // 向服务端发起登录
                const res = requestLoginApi({ authCode: res.code })
                console.log('login sucess', res)
                // 存储 token 等操作
                // ......
            } else {
                // 
            }
        }
    })
}

异步问题

如果用户从订阅消息中直接进入用户数据相关的页面时,比如订单详情,由于登录异步问题,订单详情数据在页面中直接请求会获取失败。

因此在需要校验用户登录状态的页面(比如用户信息、用户订单等)需要在自动登录完成后再渲染,类似于在小程序中实现一个路由守卫的功能。

方案

1. EventBus

考虑使用 事件中心 来调度,首先在自动登录完成时触发通知用户登录完成事件

// 该方法进入小程序时会尝试调用,自动登录
async function userLogin() {
    wx.login({
        async success(res) {
            if (res.code) {
                // 向服务端发起登录
                const res = requestLoginApi({ authCode: res.code })
                console.log('login sucess', res)
                // 存储 token 等操作
                // ......
                uni.$emit('logined')
            } else {
                // 
            }
        }
    })
}

然后新建一个eventBus/loginEvent.js 文件

let flagUserLogin = false
export const loadEventName = 'USER_LOGINED'

export const waitUserLogin = () => {
  return new Promise((resolve) => {
    if (flagUserLogin) {
      resolve()
    } else {
      uni.$on(loadEventName, () => {
        flagUserLogin = true
        resolve()
      })
    }
  })
}

在页面中使用:

async onload() {
    await waitUserLogin()
    // 获取用户相关数据
    this.fetchData()
}