Client - cancel duplicate api calls

This commit is contained in:
Sam 2022-09-19 10:53:31 +02:00
parent 6982f5320a
commit a040b0c845
5 changed files with 73 additions and 3 deletions

View File

@ -1,5 +1,6 @@
import axios from 'axios' import axios from 'axios'
import { pendingRequests, removeRequestIfPending } from '@/api/pending'
import store from '@/store' import store from '@/store'
import { AUTH_USER_STORE } from '@/store/constants' import { AUTH_USER_STORE } from '@/store/constants'
import { getApiUrl } from '@/utils' import { getApiUrl } from '@/utils'
@ -10,6 +11,11 @@ const authApi = axios.create({
authApi.interceptors.request.use( authApi.interceptors.request.use(
(config) => { (config) => {
const controller = new AbortController()
config.signal = controller.signal
const requestKey = removeRequestIfPending(config)
pendingRequests.set(requestKey, controller)
const authToken = store.getters[AUTH_USER_STORE.GETTERS.AUTH_TOKEN] const authToken = store.getters[AUTH_USER_STORE.GETTERS.AUTH_TOKEN]
if (authToken) { if (authToken) {
const auth = `Bearer ${authToken}` const auth = `Bearer ${authToken}`
@ -22,4 +28,17 @@ authApi.interceptors.request.use(
(error) => Promise.reject(error) (error) => Promise.reject(error)
) )
authApi.interceptors.response.use(
(response) => {
removeRequestIfPending(response.config)
return response
},
(error) => {
if (error.message !== 'canceled') {
removeRequestIfPending(error.response.config)
}
return Promise.reject(error)
}
)
export default authApi export default authApi

View File

@ -1,9 +1,34 @@
import axios from 'axios' import axios from 'axios'
import { pendingRequests, removeRequestIfPending } from '@/api/pending'
import { getApiUrl } from '@/utils' import { getApiUrl } from '@/utils'
const api = axios.create({ const api = axios.create({
baseURL: getApiUrl(), baseURL: getApiUrl(),
}) })
api.interceptors.request.use(
(config) => {
const controller = new AbortController()
config.signal = controller.signal
const requestKey = removeRequestIfPending(config)
pendingRequests.set(requestKey, controller)
return config
},
(error) => Promise.reject(error)
)
api.interceptors.response.use(
(response) => {
removeRequestIfPending(response.config)
return response
},
(error) => {
if (error.message !== 'canceled') {
removeRequestIfPending(error.response.config)
}
return Promise.reject(error)
}
)
export default api export default api

View File

@ -0,0 +1,18 @@
import { AxiosRequestConfig } from 'axios'
export const pendingRequests = new Map()
const generateRequestKey = (config: AxiosRequestConfig): string => {
const { method, url, params = {}, data = {} } = config
return [method, url, JSON.stringify(params), JSON.stringify(data)].join('')
}
export const removeRequestIfPending = (config: AxiosRequestConfig): string => {
const requestKey = generateRequestKey(config)
if (pendingRequests.has(requestKey)) {
const controller = pendingRequests.get(requestKey) || {}
controller?.abort()
pendingRequests.delete(requestKey)
}
return requestKey
}

View File

@ -142,8 +142,10 @@ export const actions: ActionTree<IAuthUserState, IRootState> &
} }
}) })
.catch((error) => { .catch((error) => {
if (error.message !== 'canceled') {
handleError(context, error) handleError(context, error)
removeAuthUserData(context) removeAuthUserData(context)
}
}) })
}, },
[AUTH_USER_STORE.ACTIONS.LOGIN_OR_REGISTER]( [AUTH_USER_STORE.ACTIONS.LOGIN_OR_REGISTER](

View File

@ -28,7 +28,12 @@ export const handleError = (
error: AxiosError | null, error: AxiosError | null,
msg = 'UNKNOWN' msg = 'UNKNOWN'
): void => { ): void => {
// if stored token is blacklisted // if request is cancelled, no error to display
if (error && error.message === 'canceled') {
return
}
// if stored token is blacklisted, disconnect user
if ( if (
error?.response?.status === 401 && error?.response?.status === 401 &&
error.response.data.error === 'invalid_token' error.response.data.error === 'invalid_token'
@ -37,6 +42,7 @@ export const handleError = (
context.dispatch(AUTH_USER_STORE.ACTIONS.CHECK_AUTH_USER) context.dispatch(AUTH_USER_STORE.ACTIONS.CHECK_AUTH_USER)
return return
} }
const errorMessages = !error const errorMessages = !error
? msg ? msg
: error.response : error.response