You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 21:30:59