Promise.prototype.finally 适合隐藏全局 Loading,因其在 Promise settled 后必执行,避免 then/catch 分支遗漏或重复;它不接收参数、不影响链式结果,故仅用于收尾操作如 hideLoading。

用 Promise.prototype.finally 隐藏全局 Loading 是简洁可靠的做法:它不关心 Promise 最终是 fulfilled 还是 rejected,只要状态 settled 就执行,天然适合收尾操作。
为什么 finally 比 then/catch 更合适
在请求后手动控制 Loading 显示/隐藏时,容易遗漏错误分支:
- 只在
.then()里关 Loading → 请求失败时 Loading 一直挂着 - 在
.then()和.catch()都写关 Loading → 重复代码,维护成本高 - 用
try/catch+async/await也能实现,但需包裹整个逻辑,不如finally直观轻量
基础用法:配合 axios 或 fetch
假设你有一个全局的 showLoading() 和 hideLoading() 函数(比如基于 Element Plus 的 ElLoading.service 或自定义状态):
showLoading();
axios.get('/api/data')
.then(res => console.log(res.data))
.catch(err => console.error('请求失败', err))
.finally(() => hideLoading()); // ✅ 无论成功失败都会执行
如果是 async/await 写法,同样适用:
showLoading();
try {
const res = await axios.get('/api/data');
console.log(res.data);
} catch (err) {
console.error('请求失败', err);
} finally {
hideLoading(); // ✅ 保证执行
}
进阶:封装成可复用的请求函数
把 Loading 控制逻辑内聚到请求层,业务代码更干净:
function requestWithLoading(config) {
showLoading();
return axios(config)
.finally(() => hideLoading());
}
// 使用时无需关心 Loading
requestWithLoading({ url: '/api/user', method: 'get' })
.then(res => console.log(res.data))
.catch(err => console.error(err));
还可支持手动控制是否启用 Loading:
function request(config, options = {}) {
const { loading = true } = options;
if (loading) showLoading();
return axios(config).finally(() => {
if (loading) hideLoading();
});
}
注意点:finally 不接收参数,也不影响链式结果
finally 回调没有参数,且它的返回值不会改变原始 Promise 的结果:
- 不能在
finally里直接拿到响应数据或错误对象 —— 需要靠前面的then或catch处理 - 如果
finally中返回一个 Promise,它会等待完成,但不会改变上一级 Promise 的 resolved 值 - 不要在
finally里做依赖响应数据的逻辑,比如跳转、弹窗提示等 —— 这些仍应放在then/catch中










