У меня есть перехватчик на месте, чтобы поймать 401 ошибки, если истекает токен доступа. Если он истекает, он пытается обновить токен, чтобы получить новый токен доступа. Если в течение этого времени выполняются любые другие вызовы, они ставятся в очередь до тех пор, пока токен доступа не будет проверен.
Все это работает очень хорошо. Однако при обработке очереди с использованием Axios (originalRequest) первоначально вложенные обещания не вызываются. Ниже приведен пример.
Рабочий код перехватчика:
Axios.interceptors.response.use(
response => response,
(error) => {
const status = error.response ? error.response.status : null
const originalRequest = error.config
if (status === 401) {
if (!store.state.auth.isRefreshing) {
store.dispatch('auth/refresh')
}
const retryOrigReq = store.dispatch('auth/subscribe', token => {
originalRequest.headers['Authorization'] = 'Bearer ' + token
Axios(originalRequest)
})
return retryOrigReq
} else {
return Promise.reject(error)
}
}
)
Метод обновления (используется токен обновления для получения нового токена доступа)
refresh ({ commit }) {
commit(types.REFRESHING, true)
Vue.$http.post('/login/refresh', {
refresh_token: store.getters['auth/refreshToken']
}).then(response => {
if (response.status === 401) {
store.dispatch('auth/reset')
store.dispatch('app/error', 'You have been logged out.')
} else {
commit(types.AUTH, {
access_token: response.data.access_token,
refresh_token: response.data.refresh_token
})
store.dispatch('auth/refreshed', response.data.access_token)
}
}).catch(() => {
store.dispatch('auth/reset')
store.dispatch('app/error', 'You have been logged out.')
})
},
Метод Subscribe в модуле auth/actions:
subscribe ({ commit }, request) {
commit(types.SUBSCRIBEREFRESH, request)
return request
},
Как и Мутация:
[SUBSCRIBEREFRESH] (state, request) {
state.refreshSubscribers.push(request)
},
Вот пример действия:
Vue.$http.get('/users/' + rootState.auth.user.id + '/tasks').then(response => {
if (response && response.data) {
commit(types.NOTIFICATIONS, response.data || [])
}
})
Если этот запрос был добавлен в очередь I, потому что токен обновления должен был получить доступ к новому токену, я хотел бы добавить оригинал then():
const retryOrigReq = store.dispatch('auth/subscribe', token => {
originalRequest.headers['Authorization'] = 'Bearer ' + token
// I would like to attache the original .then() as it contained critical functions to be called after the request was completed. Usually mutating a store etc...
Axios(originalRequest).then(//if then present attache here)
})
После обновления токена доступа очередь запросов обрабатывается:
refreshed ({ commit }, token) {
commit(types.REFRESHING, false)
store.state.auth.refreshSubscribers.map(cb => cb(token))
commit(types.CLEARSUBSCRIBERS)
},