如何正确缓存 Promise 以避免重复请求

老强姑娘_1118

老强姑娘_1118

2026-07-10

494人浏览

原创

如何正确缓存 Promise 以避免重复请求

本文详解在 angular 等异步环境中缓存 promise 的核心原理与实践方案,重点解决因并发调用导致缓存失效、重复请求第三方 api 的问题,并提供顺序执行与去重预加载两种高效解决方案。

本文详解在 angular 等异步环境中缓存 promise 的核心原理与实践方案,重点解决因并发调用导致缓存失效、重复请求第三方 api 的问题,并提供顺序执行与去重预加载两种高效解决方案。

在实际开发中,当多个 UI 组件或数据行(如表格列表)频繁请求同一用户 ID 的数据时,若未妥善处理 Promise 缓存逻辑,极易触发重复 HTTP 请求——即使缓存服务已存在对应值,仍会因并发调用时机错位而“错过”缓存命中。根本原因在于:forEach 是同步遍历,不会等待内部的 Promise 完成,导致所有 getUser(userId) 几乎同时发起,此时缓存尚未写入,每次均穿透至第三方 API。

✅ 正确做法一:顺序执行(适用于依赖严格时序或需逐条处理响应的场景)

使用 for...of + await 确保请求串行化,天然规避竞态:

// ✅ 推荐:顺序执行,保证缓存写入后才发起下一次查询
for (const row of data) {
  try {
    const user = await this.getUser(row.userId);
    // ✅ 此时 user 必然来自缓存(第二次起)或首次请求结果
    this.processUser(row, user);
  } catch (error) {
    console.error(`Failed to fetch user ${row.userId}`, error);
  }
}

对应修正后的 getUser 方法(移除冗余 async/await,避免 Promise 构造反模式):

getUser(userId: number): Promise<any> {
  const cached = this.cacheService.get(userId);
  if (cached) {
    return Promise.resolve(cached); // 直接返回已解析的 Promise
  }

  // 发起真实请求并缓存结果
  return this.THIRDPARTYAPI.getUser(userId)
    .then(user => {
      this.cacheService.put(user.id, user);
      return user;
    });
}</any>

⚠️ 注意:new Promise(async (resolve) => { ... }) 属于反模式——async 回调无法被 resolve 正确捕获异常,且增加不必要的嵌套。应直接链式调用 .then() 或 async/await 在调用层。

VibePaper
VibePaper

VibePaper是一款AI文本写作工具,短剧制作团队的AI协作工作台,节点式无限画布。

下载

✅ 正确做法二:批量去重 + 预加载(推荐用于高性能、高复用场景)

当 data 中存在大量重复 userId 时,最优解是先提取唯一 ID,统一请求并填充缓存,再遍历消费:

// ✅ 高效:一次去重 + 并发预加载,最大化缓存命中率
const uniqueUserIds = [...new Set(data.map(row => row.userId))];
const userPromises = uniqueUserIds.map(id => this.getUser(id));

try {
  const users = await Promise.all(userPromises);
  const userMap = new Map(users.map(u => [u.id, u]));

  // ✅ 此时所有 getUser() 调用均命中缓存
  data.forEach(row => {
    const user = userMap.get(row.userId);
    if (user) {
      this.processUser(row, user);
    }
  });
} catch (error) {
  console.error('Failed to preload users', error);
}

? 关键原则总结

  • 缓存本质是状态共享:Promise 本身可被多次 .then() 订阅,因此「缓存 Promise 实例」比「缓存结果值」更优(避免重复 resolve);
  • 避免 forEach + Promise 组合:它不提供并发控制,永远是“火球式”并发;
  • 优先 Promise.all + 去重:对重复 ID 场景吞吐量最高;
  • 慎用 await 在循环中:虽能解决问题,但牺牲了并发收益;仅在业务逻辑强依赖前序结果时选用。

通过合理设计缓存策略与调用方式,即可在不修改第三方库的前提下,显著降低网络开销,提升应用响应性能与用户体验。

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
promise的用法
promise的用法

“promise” 是一种用于处理异步操作的编程概念,它可以用来表示一个异步操作的最终结果。Promise 对象有三种状态:pending(进行中)、fulfilled(已成功)和 rejected(已失败)。Promise的用法主要包括构造函数、实例方法(then、catch、finally)和状态转换。

2023.10.12

4940

6

html文本框类型介绍
html文本框类型介绍

html文本框类型有单行文本框、密码文本框、数字文本框、日期文本框、时间文本框、文件上传文本框、多行文本框等等。详细介绍:1、单行文本框是最常见的文本框类型,用于接受单行文本输入,用户可以在文本框中输入任意文本,例如用户名、密码、电子邮件地址等;2、密码文本框用于接受密码输入,用户在输入密码时,文本框中的内容会被隐藏,以保护用户的隐私;3、数字文本框等等。

2023.10.12

4863

6

Go-Zero API开发使用教程
Go-Zero API开发使用教程

本专题聚焦Go-Zero的API开发,拆解.api描述文件的语法结构、路由与分组定义、参数绑定与校验规则,说明统一响应体、JWT鉴权、跨域与接口文档生成的落地方式,并给出网关聚合与接口测试的实践建议。

2026.11.12

100

15

Go-Zero安装与goctl环境配置教程
Go-Zero安装与goctl环境配置教程

本专题围绕Go-Zero的安装与工具链配置展开,讲清Go版本要求、goctl安装方式、代理镜像、protoc依赖与环境变量设置,说明多版本共存、升级回退与CI流水线安装的做法,并整理安装阶段的常见报错与验证步骤。

2026.11.12

60

15

Go-Zero零基础入门教程
Go-Zero零基础入门教程

本专题整理Go-Zero的入门知识,从框架定位、环境准备到跑通第一个API服务,讲清目录分层、配置加载、日志与中间件的基本用法,并对比Gin、Kratos的差异,帮助Go开发者建立整体认知,判断它是否适合当前项目。

2026.11.12

60

15

Postman身份认证怎么配置
Postman身份认证怎么配置

本专题从实际API接口调试场景出发,讲解Postman身份认证的完整配置流程,包括常见认证协议介绍、授权参数设置、访问令牌填写、OAuth 2.0授权及认证失败排查,帮助用户正确完成接口授权与访问验证。

2026.11.06

140

12

Postman请求头Headers怎么设置
Postman请求头Headers怎么设置

围绕Postman HTTP请求头配置展开,讲解Headers选项的具体使用方式,包括Key和Value参数填写、请求头信息添加、常见Header字段设置及请求头修改方法,帮助用户解决接口调试过程中遇到的请求头配置问题。

2026.11.06

120

13

Postman接口请求发送教程
Postman接口请求发送教程

详细介绍Postman接口请求的创建与发送方法,涵盖GET和POST请求、URL配置、请求参数、Headers请求头、Body请求体设置以及响应结果查看,帮助用户掌握Postman接口请求的完整操作流程。

2026.11.06

120

10

DBeaver怎么导入数据
DBeaver怎么导入数据

DBeaver数据导入专题,整理Excel、CSV、SQL、TXT等常见文件的数据导入方法,涵盖目标数据库选择、数据表创建、字段映射、数据类型设置及导入参数配置等操作,帮助用户将本地文件中的数据写入数据库,并了解批量导入、重复数据处理和导入失败等常见问题的解决方法。

2026.11.05

100

12

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
热门推荐
/
最新课程
phpStudy极速入门视频教程
phpStudy极速入门视频教程

共6课时 | 54.7万人学习

独孤九贱(4)_PHP视频教程
独孤九贱(4)_PHP视频教程

共89课时 | 134.3万人学习