如何实现getOrFetchCategoriesList避免重复发送未完成的后端请求
问题分析
你现有的代码存在两个核心问题:
- 分支逻辑有缺陷:
if (categories.length)和if (!categories.length)已经覆盖了所有分支,categoriesLoading的判断分支永远不会被执行 - 没有存储 pending 状态的请求实例,就算进入加载中分支也没有可等待的对象
最优实现方案
我们可以直接用一个 Promise 变量同时承担「状态标识」和「结果缓存」的作用,不需要单独维护加载状态和结果变量,实现更简洁也更可靠:
// 全局存储分类请求的Promise,初始为null let categoriesPromise: Promise<Category[]> | null = null; const getOrFetchCategoriesList = async (): Promise<Category[]> => { // 已经存在请求Promise(不管是 pending 还是已 resolve),直接返回即可 if (categoriesPromise) { return categoriesPromise; } // 无请求时发起新请求,将Promise存入全局变量 categoriesPromise = (async () => { const response: ElasticsearchAnswer = await fetchCategoryList(); return response.hits.hits.map(hit => hit._source); })(); return categoriesPromise; }; // 可选:如果后续有清空缓存重新请求的需求,可以增加重置方法 const resetCategoriesCache = () => { categoriesPromise = null; };
逻辑说明
这个实现完全覆盖你提出的三个要求:
- 首次调用时
categoriesPromise为null,会发起新请求 - 请求成功后
categoriesPromise处于已 resolve 状态,后续所有调用都会直接返回缓存的结果,不会重复发起请求 - 请求过程中如果有新的调用,会直接返回同一个 pending 状态的Promise,所有调用方都会等待同一份请求结果,不会发起重复请求
内容的提问来源于stack exchange,提问作者Nimble Stalker
相关产品推荐
相关产品推荐

