Axios响应拦截器导致Redux Saga中API调用失效,求修复方案
React Native + Redux Saga 添加Axios响应拦截器后API调用失效的修复方案
我有一个React Native项目,采用Redux Saga机制处理API调用。添加Axios响应拦截器后,Saga中的API调用直接失败,求修复方法。
Axios实例及拦截器原代码
const getLoggedInUser = async () => { const savedUser = JSON.parse( await getDataFromAsyncStorage(APP_CONSTANTS.SAVED_USER) ) if (savedUser?.user_id != null) { return savedUser } return null } const baseapi = axios.create({ baseURL: APP_CONSTANTS.BASE_URL, headers: {}, }) baseapi.interceptors.request.use( async (config) => { const token = await getLoggedInUser() const userId = token?.user_id const authToken = token?.token if (token) { baseapi.defaults.headers.common['userId'] = token baseapi.defaults.headers.common['token'] = authToken } return config }, (error) => { return Promise.reject(error) } ) // Response interceptor for API calls baseapi.interceptors.response.use( (response) => { return response }, async function (error) { const originalRequest = error.config if (error.response.status === 403 /* && !originalRequest._retry */) { return baseapi(originalRequest) } return Promise.reject(error) } )
Saga原代码
function* getTopicList(action) { try { yield put({type: ACTION_TYPES.START_TOPIC_LIST}) const {payload} = action const res = yield call(getAllTopicsOfBatch, payload) if (res?.status == APP_CONSTANTS.SUCCESS_STATUS) { yield put({ type: ACTION_TYPES.SET_TOPIC_LIST, payload: {data: res?.data?.topics}, }) } else { alert('OOPS Something went wrong! Please try again') yield put({ type: ACTION_TYPES.ERROR_TOPIC_LIST, payload: 'Something Went Wrong Please Try Again', }) } } catch (error) { console.log('RESPONES error', error) alert('OOPS Something went wrong! Please try again') yield put({ type: ACTION_TYPES.ERROR_TOPIC_LIST, payload: 'Something Went Wrong Please Try Again', }) } }
修复方案
1. 修正Axios拦截器的关键问题
请求拦截器问题:
- 错误修改全局
baseapi.defaults.headers,会污染后续请求的headers,异步场景下还会引发竞态问题。 userId字段赋值错误,将整个token对象赋值给了userId,应该使用token?.user_id。
响应拦截器问题:
- 未添加
_retry标记,403时会无限重试请求,导致死循环。 - 未处理
error.response不存在的情况(比如网络错误),会直接抛出异常。
修复后的Axios代码:
const getLoggedInUser = async () => { const savedUser = JSON.parse( await getDataFromAsyncStorage(APP_CONSTANTS.SAVED_USER) ) if (savedUser?.user_id != null) { return savedUser } return null } const baseapi = axios.create({ baseURL: APP_CONSTANTS.BASE_URL, headers: {}, }) baseapi.interceptors.request.use( async (config) => { const token = await getLoggedInUser() const userId = token?.user_id const authToken = token?.token // 复制当前请求的headers,避免修改全局配置 const updatedHeaders = {...config.headers} if (token) { updatedHeaders['userId'] = userId // 修正userId赋值 updatedHeaders['token'] = authToken } // 返回修改后的config,不影响全局默认配置 return {...config, headers: updatedHeaders} }, (error) => { return Promise.reject(error) } ) baseapi.interceptors.response.use( (response) => { return response }, async function (error) { const originalRequest = error.config // 先判断error.response是否存在,处理网络错误等场景 if (error.response?.status === 403 && !originalRequest._retry) { originalRequest._retry = true // 标记已重试,防止无限循环 // 若需要刷新token,可在此处添加逻辑后更新请求headers // const newToken = await refreshAuthToken() // originalRequest.headers['token'] = newToken return baseapi(originalRequest) } return Promise.reject(error) } )
2. 确保API调用使用配置好的Axios实例
检查getAllTopicsOfBatch函数,确保它是使用上述baseapi实例发起请求,而非默认的axios:
// 示例:getAllTopicsOfBatch的正确实现 const getAllTopicsOfBatch = (payload) => { return baseapi.get('/api/topics/batch', { params: payload }) }
3. Saga代码补充优化(可选)
可以在Saga中更精准地捕获错误信息,方便调试:
function* getTopicList(action) { try { yield put({type: ACTION_TYPES.START_TOPIC_LIST}) const {payload} = action const res = yield call(getAllTopicsOfBatch, payload) if (res?.status === APP_CONSTANTS.SUCCESS_STATUS) { yield put({ type: ACTION_TYPES.SET_TOPIC_LIST, payload: {data: res?.data?.topics}, }) } else { const errorMsg = res?.data?.message || 'Something Went Wrong Please Try Again' alert(`OOPS! ${errorMsg}`) yield put({ type: ACTION_TYPES.ERROR_TOPIC_LIST, payload: errorMsg, }) } } catch (error) { console.log('TOPIC LIST ERROR:', error.response?.data || error.message) const errorMsg = error.response?.data?.message || 'Something Went Wrong Please Try Again' alert(`OOPS! ${errorMsg}`) yield put({ type: ACTION_TYPES.ERROR_TOPIC_LIST, payload: errorMsg, }) } }
内容的提问来源于stack exchange,提问作者Rahul Vyas
相关产品推荐
相关产品推荐

