uniapp(vue2):用户数据用的vuex设置,在应用启动方法onLaunch开始获取。请问我在页面onLoad事件中获取vuex中的user数据时,如何等待user获取成功后再往下执行?

我在使用uniapp(vue2)开发小程序,用户数据用的vuex设置,在应用启动方法onLaunch开始获取。请问我在页面onLoad事件中获取vuex中的user数据时,如何等待user获取成功后再往下执行?

  1. 在App.vue中,使用Promise封装登录接口的调用,并在登录成功后返回一个resolve。
    此方法可以实现,但是如果我有多个启动参数呢?比如有user、config,是要设置多个Promise?比如,我要等待user的时候就监听user的Promise?
  2. 轮询,如果user为空时,递归查询,一直到查询出结果
请问是否还有其他好的处理方案,因为我不是前端出身,想看看各位前端大佬有什么好的处理方式
阅读 1.3k
3 个回答

可以使用 store 的 subscribe 方法订阅 mutation

当 store 里存储的数据发生改变时,就会触发 subscribe 里的回调函数

不需要订阅时在使用 unsubscribe 停止订阅

具体可参考官方文档里的 subscribe

image.png

一般来说,获取用户信息的操作会放到 Vuex 里面来维护的,比如说:

// src/store/modules/user.js

// ... 上下文

const actions = {
  // get user info
  getInfo({ commit, state }) {
    return new Promise((resolve, reject) => {
      getInfo(state.token).then(response => {
        const { data } = response

        if (!data) {
          reject('Verification failed, please Login again.')
        }

        const { roles, name, avatar, introduction } = data

        // roles must be a non-empty array
        if (!roles || roles.length <= 0) {
          reject('getInfo: roles must be a non-null array!')
        }

        commit('SET_ROLES', roles)
        commit('SET_NAME', name)
        commit('SET_AVATAR', avatar)
        commit('SET_INTRODUCTION', introduction)
        resolve(data)
      }).catch(error => {
        reject(error)
      })
    })
  }
}

const mutations = {
  SET_TOKEN: (state, token) => {
    state.token = token
  },
  SET_INTRODUCTION: (state, introduction) => {
    state.introduction = introduction
  },
  SET_NAME: (state, name) => {
    state.name = name
  },
  SET_AVATAR: (state, avatar) => {
    state.avatar = avatar
  },
  SET_ROLES: (state, roles) => {
    state.roles = roles
  }
}

// ... 上下文

可以看到 getInfo 这个 ActionPromisify 的,那么我们在业务逻辑中就可以这样使用:

// src/permission.js

// ... 上下文
try {
  // get user info
  // note: roles must be a object array! such as: ['admin'] or ,['developer','editor']
  const { roles } = await store.dispatch('user/getInfo')

  // generate accessible routes map based on roles
  const accessRoutes = await store.dispatch('permission/generateRoutes', roles)

  // dynamically add accessible routes
  router.addRoutes(accessRoutes)

  // hack method to ensure that addRoutes is complete
  // set the replace: true, so the navigation will not leave a history record
  next({ ...to, replace: true })
} catch (error) {
  // remove token and go to login page to re-login
  await store.dispatch('user/resetToken')
  Message.error(error || 'Has Error')
  next(`/login?redirect=${to.path}`)
  NProgress.done()
}

// ... 上下文

这样就可以起到OP你需求的 等待user获取成功后再往下执行。在获取到用户登录之后到系统返回信息之前会一直显示 Loading 状态,而不是直接进入系统。

至于进入系统之后一些的业务逻辑,可能接口没有返回但还是需要正常展示业务页面。就需要使用到其他回复中提到的一些占位信息的展示和骨架屏


其实你可以直接借鉴开源的项目来实现对应的需求,比如说现在使用量比较大的两个国内后台管理框架:

一些相关的文档资源:

写 vue 这类响应式框架,要更改写代码的习惯。你需要考虑的不是等待 user 获取到,而是需要考虑,还没有获取到 user 时页面要如何展示。

你可以在 app.vue 最外层的 view 上增加一个 v-if="user" ,这样只有 user 信息到达之后才会开始渲染页面。


  1. 可以设置多个 promise ,分别获取并写入 vuex 中即可。
  2. 如果后端服务比较稳定,那么最好的方式是提供用户一个手动出发的入口,比如下拉刷新之类的。使用轮询的话也可以,但是要注意控制好轮询的时间并及时清除 timer 。
宣传栏