当前位置: 首页 > news >正文

Promise执行顺序踩坑

finally执行时机

在 JavaScript 的 Promise 中,finally() 方法会在 Promise 状态确定(无论是 fulfilled 成功还是 rejected 失败)后无条件执行,与前面的 then()catch() 是否执行无关。

finally() 起作用的关键条件

  • Promise 已完成(settled):即状态变为 fulfilled 或 rejected,此时 finally() 回调会被触发。
  • 无论链中是否有 then()catch():即使前面没有 then()catch(),只要 Promise 状态确定,finally() 仍会执行。
  • 即使 then()catch() 中抛出新错误:finally() 依然会执行(但后续的错误可能被后续的 catch() 捕获。

典型使用场景

  • 资源清理:如关闭文件句柄、数据库连接。
  • UI 状态重置:如隐藏加载动画、禁用按钮。
  • 避免重复代码:统一处理成功/失败后的收尾逻辑,无需在 then()catch() 中分别写。
示例说明
Copy Code
Promise.resolve('成功').finally(() => console.log('finally 执行')) // 输出:finally 执行.then(value => console.log(value)); // 输出:成功Promise.reject('失败').finally(() => console.log('finally 执行')) // 输出:finally 执行.catch(err => console.log(err)); // 输出:失败

✅ 关键点:finally() 不接收参数,无法得知 Promise 的结果;也不改变 Promise 的值,原结果会继续向下传递。

注意事项

finally() 是 ES2018(ES9)引入的,旧环境需使用 polyfill 兼容。
不要在 finally() 中修改 Promise 的状态或返回新 Promise(除非明确需要等待它完成),否则可能掩盖原始结果。
综上,只要 Promise 实例完成(无论成功或失败),finally() 就会起作用,适用于任何需要“无论如何都要执行”的清理逻辑。


这段代码之所以在 console.log 中看不到“地址”项,核心原因在于异步请求的时序问题

console.logfinally 代码块在 getLocation() 发起后立即执行,此时 reverseGeocoder(逆地址解析)还没有返回结果,导致 wm 数组尚未被填入地址信息。

🔍 根本原因分析

JavaScript 中的 Promise 是异步执行的。代码的执行顺序如下:

  1. 调用 getLocation()
  2. (异步) 代码不等待 getLocationthen 内部执行完毕,直接跳到外部的 .finally()
  3. 执行 .finally():此时 wm 数组里只有“人员”(甚至可能只有“人员”,取决于 getLocation 的解析速度),绝对没有“地址”,因为 reverseGeocoder 还没跑完。
  4. 执行 console.log('水印', wm)
  5. (稍后) getLocation 成功,进入第一个 then
  6. (更晚) reverseGeocoder 成功,向 wm 推送“地址”。但此时 console.log 早就已经打印完了。

✅ 解决方案

你需要确保在所有异步操作(获取位置 + 获取地址)都完成后,再执行日志打印和水印添加操作。

推荐使用 async/await 来重写,这样代码逻辑是线性的,更容易理解且不易出错。

修改后的代码示例

async addImages(filePaths) {var wm = [];try {// 1. 等待获取位置结果const res = await getLocation();// 2. 添加人员信息wm.push('人员:' + uni.getStorageSync('ratelName'));// 3. 等待逆地址解析结果let poisTitle = "";const addr = await reverseGeocoder(res);if (addr.result.pois && addr.result.pois.length > 0) {poisTitle = addr.result.pois[0].title;}const address = addr.result.address + '-' + poisTitle;wm.push('地址:' + address);// 4. 添加时间wm.push("时间:" + this.getNowTime());// 5. 此时所有数据都准备好了,再打印和添加水印console.log('水印', wm);if (filePaths.length > 0) {this.$refs.watermark.addWaterMark({filePaths,fillTexts: wm});}} catch (e) {console.error('获取水印信息失败', e);// 可选:即使失败也添加水印,但不带地址或带默认地址}
},

💡 为什么这样做有效?

  • await 会暂停函数的执行,直到 Promise 完成。
  • 代码会按顺序执行:先拿到位置 -> 再拿到地址 -> 再组装数组 -> 最后打印。
  • 不再需要 .finally() 来处理逻辑,.finally() 通常用于关闭加载动画或清理资源,而不适合用于依赖异步结果的逻辑处理。
http://www.jsqmd.com/news/613226/

相关文章:

  • STM32CubeMX实战:USART/UART中断与空闲中断实现命令解析与LED控制
  • 终极指南:5步快速实现Degrees of Lewdity完整中文本地化
  • HTML 5元素
  • ROS2 Humble下D455深度相机与VINS-Fusion的实战融合:从配置调优到稳定运行
  • Win11Debloat终极指南:一键清理Windows 11臃肿系统,提升性能与隐私
  • Win11Debloat终极指南:5分钟让你的Windows系统飞起来!
  • 从零开始掌握Common Voice数据集:构建多语言语音识别系统的终极指南
  • 别再乱设bias了!PyTorch中nn.Conv2d与BatchNorm2d搭配的黄金法则
  • 告别查重焦虑!PaperXie 四大检测方案,精准匹配本科论文全场景需求
  • 聚焦双层及夹套玻璃反应釜:剖析技术先进、实力强劲的优质品牌厂家 - 品牌推荐大师
  • Qwen3-VL-WEBUI零基础入门:手把手教你玩转阿里视觉大模型
  • DeepSeek专家模式万字长文深度解析:思维链推理如何颠覆AI辅助编程与学术研究
  • 3步驯服性能野兽:Turbo Boost Switcher让系统稳定性提升40%
  • 原子化刻意练习习得性乐观的庖丁解牛
  • 鸣潮自动化工具全攻略:从入门到精通的效率倍增指南
  • OpenClaw浏览器自动化:Qwen2.5-VL-7B实现网页图文信息抓取与归档
  • 如何用Python一键备份你的QQ空间历史说说?
  • 2026汕头定制整体衣柜选型指南:满足这3个硬指标才算靠谱 - 精选优质企业推荐榜
  • 终极指南:在电脑上完美运行任天堂Switch游戏的完整方案
  • Perseus原生库架构设计与无偏移脚本补丁技术实现
  • 基于多源基因组数据的系统发育树构建策略与实践
  • 中兴光猫权限解锁终极指南:zteOnu工具一键获取管理员权限
  • 2026汕头全屋定制上门量尺选型指南:满足这3个硬指标才算靠谱 - 精选优质企业推荐榜
  • HY-Motion 1.0保姆级教程:从安装到导出FBX,30分钟搞定3D动作生成
  • 深入解析ALV-Layout参数:从基础配置到高级应用
  • 终极指南:5分钟在Windows上自动安装最新ADB和Fastboot驱动
  • FanControl本地化配置零门槛教程:让你的风扇控制软件说中文
  • DoraMate 项目(19) - DoraMate 项目 MVP 总结:从可视化编排到本地运行闭环的阶段性复盘
  • Go context 取消信号传播逻辑
  • 探讨学西点学校的选购,广州优美西点值得选吗? - 工业品牌热点