如何避免Vue3+TypeScript+Axios项目因未处理的Promise拒绝导致应用崩溃?
嘿,我之前在Vue3+TypeScript+Axios的项目里也踩过这个一模一样的大坑!明明在Axios拦截器里写了错误提示逻辑,结果用await axios.post(...)发请求碰到409这类错误时,还是直接黑屏崩溃,折腾了半天才搞明白问题出在哪,给你分享几个亲测有效的解决办法:
1. 先把Axios拦截器的错误处理逻辑补全——别“吞”错误
这是最容易踩的坑!你在拦截器里处理完错误(比如弹提示)之后,一定要把错误重新抛出去,或者返回一个被拒绝的Promise。因为Axios的请求是基于Promise链的,如果你在错误拦截器里不把拒绝状态传递下去,组件里的await会误以为请求成功了,但实际上错误会变成未捕获的Promise拒绝,直接导致崩溃。
给你看个修正后的拦截器代码示例:
instance.interceptors.response.use( response => response, error => { // 这里是你的自定义错误处理逻辑,比如弹提示、处理401权限跳转 if (error.response?.status === 409) { // 你的自定义弹窗/提示逻辑 showAlert("资源冲突啦,请稍后再试~"); } else { showErrorModal(`请求出错:${error.message}`); } // 重点!必须把错误抛出去,让Promise链保持拒绝状态 return Promise.reject(error); // 或者直接写 throw error; 效果是一样的 } );
2. 组件里的await请求一定要用try/catch包裹——哪怕拦截器已经处理了
很多人以为拦截器处理了错误,组件里就不用管了,但真不是这样!拦截器把错误抛出去之后,组件里的await如果没有被try/catch包裹,这个错误就会变成未处理的Promise拒绝,Vue3在生产环境下直接就崩了。
正确的组件请求写法示例:
async function submitForm() { try { const res = await instance.post("/api/submit-form", formData.value); // 请求成功后的业务逻辑,比如重置表单、提示成功 formData.value = {}; showSuccessToast("提交成功!"); } catch (err) { // 这里可以针对当前请求做特殊处理,比如重置表单提交状态 submitLoading.value = false; // 哪怕你什么特殊逻辑都不需要,也要留个空的catch块,避免未处理的拒绝 console.debug("提交失败,已在拦截器处理错误:", err); } }
划重点:哪怕catch里什么都不做,也要加上这个块,它能接住拦截器抛过来的错误,彻底避免未处理的Promise拒绝。
3. 加个全局兜底防线——防止漏网之鱼
如果你怕项目里有些地方漏加了try/catch,可以在全局加个兜底的错误监听,把所有未处理的Promise拒绝都接住,这是最后一道保险,能避免应用直接黑屏。
在你的main.ts里加上这段代码:
// 监听全局未处理的Promise拒绝 window.addEventListener("unhandledrejection", (event) => { // 阻止浏览器的默认崩溃行为 event.preventDefault(); // 这里可以做全局错误上报,或者给用户一个友好提示 console.error("捕获到未处理的Promise拒绝:", event.reason); showGlobalError("哎呀,出了点小问题,请刷新页面再试试~"); }); // 再加上Vue3的全局错误捕获,覆盖组件内的未处理错误 app.config.errorHandler = (err, instance, info) => { console.error("Vue全局错误:", err, "错误信息:", info); showGlobalError("应用出现小故障啦,稍等片刻再试试吧~"); };
最后提醒下,开发环境下Vue3会在控制台打印“Unhandled Promise Rejection”的警告,看到这个提示一定要立刻去对应代码里检查,要么补拦截器的错误抛出,要么加try/catch,别等生产环境崩了才后悔!
内容来源于stack exchange

