ES9中新增了Promise.prototype.finally(),我们来学习下
在之前的学习中,我们知道了then
方法和catch
方法,现在我们可以想象在一个完整的外卖订餐流程中
then()
→ 外卖送到后开吃(成功)catch()
→ 送餐出错处理(失败)finally()
→ 无论成败都要被告知(必执行)
js
// 订餐流程
orderFood()
.then(food => console.log(` 享用${food}`)) // 成功吃上
.catch(err => console.log(" 投诉:", err)) // 失败处理
.finally(() => console.log(" 收拾碗筷")); // 必执行
特性描述
- 无视成败:无论Promise成功/失败都执行
- 无参数:不接收任何结果值
- 链式传递:返回原Promise结果(不改变结果)
一些常见的使用场景
关闭加载动画
js
let isLoading = true;
fetchData()
.then(data => render(data))
.catch(err => showError(err))
.finally(() => {
isLoading = false; // 必关闭加载状态
spinner.hide();
});
记录操作结束
js
trackUserAction()
.finally(() => {
console.log(`[${new Date()}] 用户操作完成`);
// 无论成功失败都记录
});
替代重复代码(避免then/catch双写)
js
// 旧写法(ES6)
fetchData()
.then(data => {
process(data);
cleanup(); // 成功时需要清理
})
.catch(err => {
handleError(err);
cleanup(); // 失败时也要清理 → 重复!
});
// 新写法(ES9)
fetchData()
.then(process)
.catch(handleError)
.finally(cleanup); // 只需写一次
finally中的异步操作
js
deleteFile()
.finally(() => {
return backupLog(); // 返回新Promise
})
.then(() => console.log(" 备份完成"))
.catch(err => console.log(" 备份失败", err));
finally抛出错误
js
saveData()
.finally(() => {
throw new Error("清理异常"); // 会覆盖原结果
})
.catch(err => console.log(err)); // 捕获清理错误
与async/await结合
js
async function fetchWithCleanup() {
try {
const data = await fetchAPI();
} catch (err) {
handleError(err);
} finally { // 等效语法
releaseResources();
}
}
与传统方案相比
场景 | ES6方案 | ES9 finally 方案 |
优势 |
---|---|---|---|
关闭数据库连接 | then/catch中重复调用db.close() |
.finally(db.close) |
避免代码重复 |
隐藏加载动画 | 每个分支写spinner.hide() |
集中写在finally | 减少50%代码量 |
释放文件句柄 | 可能遗漏错误分支 | 确保100%执行 | 防止资源泄漏 |
牢记
finally
作为Promise的兜底保障,必执行 (无视成功失败),资源管理 (防止内存泄漏), 代码精简(消除重复逻辑)