vuejs2 - 自动登录完成后请求vuejs axios
问题描述
自动登录成功后如何执行所有其他请求。代码示例。
axios.get('personal/' + this.$store.state.username + '/config/', {headers: { Authorization: 'Token ' + this.$store.state.idToken }})
有时接收用户数据(用户名和 ID)的请求没有时间传递并提交到状态,并且我收到用户名在状态下为空的错误。
我已经通过添加登录函数将用户名和 ID 保存在本地存储中解决了这个问题,并且在尝试自动登录之后我有下一个代码:
tryAutoLogin ({ commit, dispatch }) {
const token = localStorage.getItem('token')
if (!token) {
return
} else {
commit('getToken', {
key: token
})
const userId = localStorage.getItem('userId')
const username = localStorage.getItem('username')
if (!userId || !username) {
dispatch('getUser')
} else {
commit('getUserData', {
id: userId,
username: username.username
})
}
}
这种方式可以吗?或者有任何方法可以停止对 api 的任何请求,直到dispatch('getUser')
成功通过。代码示例getUser
:
getUser ({ commit, state }) {
if (!state.idToken) {
return
}
axios.get('rest-auth/user/', {headers: { Authorization: 'Token ' + state.idToken }})
.then(res => {
localStorage.setItem('username', res.data.username)
localStorage.setItem('userId', res.data.pk)
commit('getUserData', {
id: res.data.pk,
username: res.data.username
})
})
},
请不要严格,我是 FE vue js 的新手:)
解决方案
首先,让 getter、action、mutations 和 state 的名称更加简洁明了(例如 getUser 表示 getter,setUser 表示 action)。
我建议创建一个单独的身份验证模块(将所有身份验证逻辑放在此模块中)并在 Vuex 操作或应用程序中的某个位置使用它。
此类模块应通过 Vuex 的 getter、setter 和操作(例如,获取和设置当前用户身份验证状态)与 Store 交互。它使认证更加封装和清晰。
通过这种方式,您将能够从任何应用程序组件调用此模块的方法并等待结果。
在下面的代码中 ( http_auth.js
)this.$auth
是单独的身份验证模块,可以在 Vuex 中设置用户状态并获取当前状态。它还使用 localStorage 检查保存的令牌(用户数据)并尝试使用保存的令牌进行授权(tryAutoLogin
在您的情况下)。失败时,它会重定向到登录页面。
...
methods: {
async loadInitialData () {
if (await this.$auth.init()) {
axios.get('initial-data-url').then(res => ...)
}
}
},
created () {
this.loadInitialData()
}
...
Auth 方法是基于 Promise 的,所以你可以等待之前解决或拒绝。
如果您只想使用 Vuex-only 解决方案,您应该使用操作来调用 API 请求并将它们包装在 Promises 中。您还可以在其他操作中分派一些操作(例如,尝试在基本登录操作中使用保存的令牌登录)。示例代码(Vuex 操作):
LOAD_SOME_DATA ({ commit, state, getters }, id) {
return new Promise((resolve, reject) => {
if (!id) {
router.push('/')
return reject('Invalid ID passed.')
}
return axios.get(getters.GET_SOME_URL + id).then(response => {
commit('PUSH_SOME_DATA', response.data)
return store.dispatch('PROCESS_SOME_DATA').then(result => {
return resolve(response)
}, error => {
console.error('Error loading some data: ', error)
return reject(error)
})
}, error => {
router.push('/')
return reject(error)
})
})
}
上面我们封装了promise basic api-call( axios.get(getters.GET_SOME_URL + id)
),然后处理接收到的数据( PROCESS_SOME_DATA
)。然后我们可以在路由器中使用它,例如(或应用程序的任何其他部分):
store.dispatch('LOAD_SOME_DATA', to.params.id).then(result => ...)
推荐阅读
- mysql - 如何获取像这个mysql查询这样的金额和字段
- java - 如何在spring data jpa for mysql数据库中一起使用一对一和一对多关系
- php - 让 nginx 将每个请求重定向到 index.php 但不下载文件
- json - Symfony - Ajax 请求更新不起作用
- angular - 下面的代码在 Angular 8 中运行。但我需要在 Angular 6 中执行它。我该如何实现呢?
- python - Django:TimeoutError:[WinError 10060] 连接尝试-> 邮件后端设置不正确?
- javascript - 为 npm 注销 GitHub Packages
- r - R - 根据下拉列表中选择的值更新文本输入框 (tkentry) (ttkcombobox)
- node.js - 将 NodeJS 运行时从 8.10 更新到 10.x 或 12.x - AWS Amplify
- java - sdkman gradle 3.4 无法确定 java 版本