ES2018中Promise的finally()与then()的区别是什么?
Promise.finally() 和链尾空then()的核心差异
嘿,这个问题问得特别到位——不少刚接触finally()的开发者都会有这个困惑,我来给你拆解清楚两者的关键区别:
1. 返回值对Promise链的影响完全不同
- 链尾的
then():它的返回值会直接改变整个Promise链的最终状态和结果。比如你在这个then()里返回一个新值或者resolved Promise,后续的回调就会拿到这个新值:Promise.reject('出错了') .catch(err => console.error(err)) .then(() => '我是新返回值') .then(res => console.log(res)) // 会打印「我是新返回值」 finally():它的返回值几乎不会影响整个链的最终结果——不管你在finally()里返回什么,最终的Promise都会沿用前面链的状态和值。只有一种例外:如果finally()里返回一个rejected的Promise,整个链才会变成rejected状态。比如:Promise.reject('出错了') .catch(err => console.error(err)) .finally(() => '我是finally的返回值') .then(res => console.log(res)) // 会打印undefined,因为前面的catch没有返回值
2. 执行的触发条件不同
- 链尾的
then():只有当前面的Promise链处于resolved状态时才会执行。如果前面的链最终是rejected状态(比如catch里又抛出了新错误),这个then()会被跳过,直接进入后续的catch(如果有的话)。 finally():不管前面的链是resolved还是rejected,一定会执行。哪怕前面的catch抛出了新错误,finally()的逻辑也会先跑完,再把错误传递下去。比如:
换成链尾Promise.reject('初始错误') .catch(err => { throw '新的错误' }) .finally(() => console.log('清理完成')) // 一定会执行 .catch(err => console.error(err)) // 会捕获「新的错误」then()的话,这个then()就不会执行,因为catch之后是rejected状态。
3. 语义化的差异
finally()的语义非常明确:这是不管成功失败都要执行的清理逻辑,比如关闭网络连接、取消加载状态、清理临时变量这类操作,其他开发者看代码时一眼就能明白它的作用。- 链尾的
then()语义上是「处理成功状态的后续操作」,哪怕你用它来做清理,别人读代码时可能会困惑,需要额外理解这是通用的收尾逻辑,而非成功后的特定操作。
实际场景的对比
比如处理网络请求时的加载状态清理:
// 使用finally:不管请求成功/失败/报错,都会关闭loading fetch('/api/data') .then(res => res.json()) .catch(err => console.error('请求失败:', err)) .finally(() => { document.getElementById('loading-spinner').style.display = 'none' }) // 使用链尾then:如果catch里抛出新错误,loading就关不掉了 fetch('/api/data') .then(res => res.json()) .catch(err => { console.error('请求失败:', err) throw err // 抛出错误,链变为rejected状态 }) .then(() => { document.getElementById('loading-spinner').style.display = 'none' // 不会执行!loading一直显示 })
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

