TL;DR
https://github.com/SilNex/vue-practice/commit/9f385a7571cf8d13504ac8f9fbc06b04059c9f06
https://github.com/SilNex/vue-practice/tree/master/vue-axios-login
Vue 강좌를 보며,
Vue-route, axios, Vuex를 이용해 만든 간단한 Login 페이지 이다.
다만 위에 프로젝트에서 한가지 문제가 있는데, 바로 /login
페이제서 로그인 후 token
을 localstorage
에 저장하여서 beforeEnter
에 넣어 주었으나, 해당 부분이 실행되지 않고 로그인이 필요하는 메시지와 함께 /login
으로 이동하게된다.
하지만 /login
페이지에선 잠시후 로그인이 완료되었다는 알림창이 표시된다.
즉, Login인 상태가 컴포넌트에서 컴포넌트론 유지가 되는데,
새로고침이나 혹은 /mypage
에 직접적으로 접근시 state
를 유지하지 못한다.(혹은 axios
를 통해 정보를 가져오지 못한다.)
문제가 되는 동작 흐름도는 다음과 같다.
1. localstorage에 토큰이 저장되어 있지않으면?
/mypage
접근시 로그인이 필요하다는 창과 함께 로그인을 요청한다.
2. localstorage에 토큰이 저장되어 있지않으면?
/mypage
접근시 로그인이 필요하다는 창과 함께 로그인페이지로 이동한다.
하지만, 잠시후 로그인이 완료되었다는 메시지가 뜬다.
(axios로 token을 이용해 user정보를 가져왔다는 뜻)
Use promise
위의 증상을 격고 여러가지 테스트를 해본결과onlyAuthUser
이 함수안에서 dispatch로 axios를 통해 user 정보를 가져오려고 할 때 axios의 결과 처리를 기다리지 않고 이후 다음 프로세스로 진행하게 되면서 문제가 발생하는 것으로 발켜졌다.
이러한 증상에 대한 해결방법으로 javascript에 promise를 사용하여 해결할 수 있다.
먼저 dispatch에 getMemberInfo부분에
getMemberInfo({ commit }) {
return new Promise((resolve, reject) => {
let token = localStorage.getItem("access_token")
let userInfo = {}
let config = {
headers: {
"access-token": token
}
}
axios
.get("https://reqres.in/api/users/2", config)
.then(res => {
userInfo = {
id: res.data.data.id,
first_name: res.data.data.first_name,
last_name: res.data.data.last_name,
avatar: res.data.data.avatar
}
commit("loginSuccess", userInfo)
resolve()
})
.catch(err => {
alert("이메일과 비밀번호를 확인해주세요")
console.log(err)
reject()
})
})
}
위와 같이 axios를 받아오는 부분을 promise에 콜백 함수로 넣어 주고,
처리가 성공되는 부분에 resolve(), 실패하는 부분에 reject()이렇게 2가지를 추가한 뒤,
위의 dispatch 로직이 완전히 실행된 후 실행할 내용을 다음과 같이 then 구분에 넣어주면 된다.
const onlyAuthUser = (to, from, next) => {
store.dispatch("getMemberInfo").then(() => {
if (store.state.isLogin === false) {
alert("로그인이 필요한 화면입니다.")
next({ name: "login" })
} else {
next()
}
})
}