避免重复调用的Redux异步Action链式调用实现问询
解决Redux异步Thunk重复调用依赖元数据接口的问题
问题根源
同时触发多个依赖xid的异步Thunk时,每个Thunk会独立检查Redux State中的xid。由于初始状态下xid不存在,它们会各自发起元数据请求,导致重复调用接口。
解决方案:共享元数据请求Promise
通过在模块级别缓存元数据请求的Promise,让所有依赖Thunk复用同一个请求实例,从根源避免重复API调用。
步骤1:添加请求Promise缓存
在元数据Slice所在的模块中,定义模块级变量缓存正在进行的元数据请求Promise:
// 模块级变量,缓存元数据请求Promise,避免重复发起请求 let metaDataRequestPromise = null; const fetchMockMetaData = createAsyncThunk( 'metaData/fetchMockData', async () => { const response = await fetch('/api/fakeMetaData'); return await response.json(); } );
步骤2:封装获取xid的工具函数
创建通用工具函数统一处理xid获取逻辑,所有依赖Thunk都通过这个函数获取xid:
/** * 统一获取xid的工具函数 * @param {Object} thunkAPI - createAsyncThunk提供的thunkAPI对象 * @returns {Promise<string>} 返回xid */ async function getXid(thunkAPI) { // 优先从Redux State读取已存在的xid const existingXid = thunkAPI.getState().metaData.xid; if (existingXid) { return existingXid; } // 已有正在进行的请求,直接复用Promise if (metaDataRequestPromise) { const metaData = await metaDataRequestPromise; return metaData.xid; } // 发起新请求并缓存Promise metaDataRequestPromise = thunkAPI.dispatch(fetchMockMetaData()).unwrap(); try { const metaData = await metaDataRequestPromise; return metaData.xid; } finally { // 请求完成后清空缓存,确保后续需要时能重新发起请求 metaDataRequestPromise = null; } }
步骤3:修改依赖Thunk的逻辑
将两个依赖xid的异步Thunk改为调用工具函数获取xid,不再各自处理元数据请求:
const fetchMockDataDependent = createAsyncThunk( 'donk/fetchMockData', async (_, thunkAPI) => { const xid = await getXid(thunkAPI); const response = await fetch(`/api/fakeDataSuccess?xid=${xid}`); return await response.json(); } ); const fetchMockDataDependentDuplicate = createAsyncThunk( 'donk/fetchMockDataDuplicate', async (_, thunkAPI) => { const xid = await getXid(thunkAPI); const response = await fetch(`/api/fakeDataSuccess?xid=${xid}`); return await response.json(); } );
原理说明
- 模块级的
metaDataRequestPromise会在第一个Thunk发起元数据请求时被赋值,后续Thunk检测到该Promise存在时,会直接等待其完成,而非发起新的API调用。 - 请求完成后清空缓存,确保当State中的xid被清除或需要刷新时,能重新发起元数据请求。
内容的提问来源于stack exchange,提问作者Jordan Klaers
相关产品推荐
相关产品推荐

