如何管理多个React组件的异步请求?-灵析社区

577739990

React中组件A里有个获取配置数据的异步请求,列表中多个组件A就会触发多个相同的异步请求,期望是等到第一个异步请求回来进行数据缓存,剩下组件直接读取缓存来获取配置数据。 我想了一下,使用axios的拦截器把请求拦截下来处理,但是如何让剩下的组件进行等待呢?或者有什么其他思路?

阅读量:18

点赞量:0

问AI
正好昨天处理了一个类似的问题,按理说这种公共组件最好别有请求,但团队里其他人已经这么写了,而且代码已经测试过了,所以不好大改。 我这边是用一个单例去保存每次请求的结果,最后一段代码里的1000代表缓存的超时时间为1000ms(1s),如果在1s内一个请求再次发起,如果这个请求和上次请求的参数一致,就使用上次的缓存,当然如果上次请求还在pending,也不会重新发起,会一并等上次的结果。具体超时时间设多少看接口的特性,数据不会频繁变的话,设十几二十秒也可以。 最后用这个hook返回的apiCall去替换之前的请求方法就行。 import { useCallback, useState } from "react"; import { isEqual } from "lodash"; interface ResponseInfo { params: unknown[]; lastRequestTime: number; getData: () => Promise; } type PromiseValue = T extends Promise ? U : T; // eslint-disable-next-line @typescript-eslint/no-explicit-any type CommonFunc = (...p: any[]) => any; type ResponseData = { data: T; isSuccess: boolean; isError: boolean; }; type ResponseValue = { apiCall: F; data: ResponseData>>; loading: boolean; }; const responseWeakMap = new WeakMap(); const genUseSingletonApi = (apiCall: T) => (instance: CommonFunc, expiration: number) => () => { type APIReturnData = PromiseValue>; const [data, setData] = useState(); const [loading, setLoading] = useState(); const apiCallFunc = useCallback( async (...params: Parameters) => { setLoading(true); const endCallback = (res: APIReturnData) => { setLoading(false); setData(res); }; const requestInfo = responseWeakMap.get(instance); if (requestInfo) { const { getData: getResponseInfo, params: oldParams, lastRequestTime } = requestInfo; const hasResponse = isEqual(oldParams, params) && +new Date() - lastRequestTime void = () => {}; const promise: Promise = new Promise(resolveCb => { resolve = resolveCb; }); responseWeakMap.set(instance, { getData: () => promise, params, lastRequestTime: +new Date(), }); const result = await apiCall(...params); resolve(result); endCallback(result); return result; }, [], ); return { apiCall: apiCallFunc, data, loading, }; }; const someAPISingletonInstance = genUseSingletonApi(fetchDataFunc); export const useAccountingList = someAPISingletonInstance( someAPISingletonInstance, 1000, );