promise.prototype.finally() 会在 promise settle(变为 fulfilled 或 rejected)时执行清理逻辑,且不会改变最终的返回值或错误状态。调用该方法会返回一个新的 promise,该新 promise 的状态和值由原 promise 决定,而 finally 中的回调函数只是作为副作用被触发。

finally 如何确保清理代码在异步操作后运行
finally 的回调函数会在 Promise 状态确定后立即执行,无论它是成功还是失败。这意味着你可以在这里关闭文件句柄、重置 UI 状态或清除定时器,而不需要分别在 .then() 和 .catch() 中重复编写相同的清理代码。

const fetchData = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (Math.random() > 0.5) {
resolve('Data loaded');
} else {
reject(new Error('Network error'));
}
}, 1000);
});
};
fetchData()
.then(data => console.log('Success:', data))
.catch(err => console.error('Failed:', err.message))
.finally(() => console.log('Cleanup executed'));
预期结果:控制台先打印 'Success: Data loaded' 或 'Failed: Network error',随后立即打印 'Cleanup executed'。如果 Promise 被拒绝,finally 依然会执行,且错误会继续向下游传播。
finally 对返回值的影响是什么
finally 中的回调函数的返回值会被忽略,除非它抛出一个新的错误。如果回调函数返回一个 Promise,finally 链会等待该 Promise 解决,但最终的 Promise 状态仍然由原始 Promise 决定。这确保了清理逻辑的执行不会意外地改变上游数据的流向。

const originalPromise = Promise.resolve('Original Value');
const finalPromise = originalPromise.finally(() => {
console.log('Cleaning up...');
return 'Ignored Value'; // 这个返回值会被忽略
});
finalPromise.then(value => console.log('Final Value:', value));
预期结果:控制台打印 'Cleaning up...',然后打印 'Final Value: Original Value'。这表明 finally 中的返回值不会影响最终传递到 .then() 的值。
如果在 finally 中抛出异常会发生什么
如果在 finally 的回调函数中抛出了异常,这个异常会覆盖原始的 Promise 状态。也就是说,即使原始 Promise 是成功的,finally 中的错误也会导致整个链变为拒绝状态,并且错误信息将是 finally 中抛出的那个,而不是原始的错误。这在处理资源清理时非常关键,因为清理代码中的错误不应掩盖业务逻辑中的错误。
const testFinallyError = () => {
return Promise.resolve('Success')
.finally(() => {
throw new Error('Cleanup failed');
});
};
testFinallyError()
.then(val => console.log('Value:', val))
.catch(err => console.error('Caught:', err.message));
预期结果:控制台打印 'Caught: Cleanup failed'。原始的成功值 'Success' 被丢弃,错误被捕获。这验证了 finally 中抛出的异常具有最高优先级,会覆盖原始状态。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











