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() } }) }