React场景下:如何从then()调用的异步函数返回缓存值
解决异步函数结果缓存的问题
我完全懂你踩的这个坑!直接在processResponse里存cachedResult之所以不行,本质是因为异步操作的时序问题:第一次调用函数时,请求还在pending状态,cachedResult还是undefined,这时候如果再调用一次,就会重复发起请求,而不是等待第一次的结果。而且缓存的如果是最终结果,没法直接复用异步流程的Promise状态。
核心思路:缓存Promise而非最终结果
正确的做法是把整个Promise对象缓存起来,而不是等到Promise resolved之后再存结果。这样后续调用时,不管Promise是pending还是resolved状态,都能直接返回这个缓存的Promise,避免重复请求。
基础实现(非React组件环境)
// 初始化缓存变量,存Promise或者undefined let cachedPromise = null; function fetchData() { // 如果已有缓存的Promise,直接返回 if (cachedPromise) { return cachedPromise; } // 没有缓存时,发起请求并缓存Promise cachedPromise = fetch('/api/data') .then(response => response.json()) .catch(error => { // 注意:如果请求失败,最好清空缓存,下次调用可以重新发起请求 cachedPromise = null; throw error; // 把错误抛出去,让调用方处理 }); return cachedPromise; }
React组件中的适配方案
因为React组件会重新渲染,用普通变量存缓存会被重置,所以我们需要用useRef来保存缓存的Promise(useRef的.current值不会随组件渲染变化):
import { useRef } from 'react'; function MyComponent() { // 用useRef存缓存的Promise const cachedPromiseRef = useRef(null); const fetchData = async () => { if (cachedPromiseRef.current) { return cachedPromiseRef.current; } try { const promise = fetch('/api/data').then(res => res.json()); cachedPromiseRef.current = promise; const result = await promise; return result; } catch (error) { // 请求失败清空缓存,允许下次重试 cachedPromiseRef.current = null; throw error; } }; // 组件中调用fetchData的逻辑 const handleClick = async () => { try { const data = await fetchData(); console.log('数据:', data); } catch (err) { console.error('请求失败:', err); } }; return <button onClick={handleClick}>获取数据</button>; }
额外优化:支持缓存失效
如果需要让缓存可以主动失效(比如用户手动刷新),可以加一个重置缓存的方法:
const resetCache = () => { cachedPromiseRef.current = null; };
这样不管是第一次调用还是后续调用,只要有缓存的Promise,就会复用它,既保证了只发起一次请求,又符合异步函数返回Promise的要求。
内容的提问来源于stack exchange,提问作者MrJalapeno
相关产品推荐
相关产品推荐

