Promise返回400状态码时仍触发then回调执行的问题
问题根源
- 你对Promise的基础理解没错:
then仅会在Promise状态变为fulfilled(成功兑现)时触发,400等错误状态下进入then,本质是当前请求逻辑把这类错误响应当成了成功状态resolve了,和Promise本身机制无关。 - 如果你用的是原生
fetchAPI:这是fetch的默认设计,只有断网、跨域拦截、请求超时这类完全没拿到服务器响应的场景才会reject进catch,只要服务器返回了HTTP响应(哪怕是400/500错误),都会走resolve逻辑进入then。 - 如果你用的是axios这类二次封装的请求库:默认配置下2xx状态码才会resolve,非2xx会自动reject。出现400进then的情况,大概率是你全局或单请求修改了
validateStatus配置,比如设置为() => true强制所有状态都走resolve。 - 你当前的代码是嵌套Promise的回调地狱写法,内部PUT请求的错误无法被外层catch捕获,很容易出现错误漏处理的问题。
修复方案
1. 补全错误状态校验逻辑
如果用原生fetch,必须在第一层then里手动校验响应状态,不满足成功条件就主动抛错进入catch:
// fetch 校验示例 fetch("/api/v1/file/upload", { method: "POST", body: formdata }) .then(response => { // 手动校验状态,非2xx直接抛错 if (!response.ok) { return Promise.reject(new Error(`上传失败,状态码:${response.status}`)) } return response.json() })
如果用axios,先检查全局validateStatus配置,改回默认规则即可:
// axios全局配置修正 axios.defaults.validateStatus = (status) => { // 仅2xx状态判定为成功 return status >= 200 && status < 300 }
如果需要保留特殊的validateStatus配置,也可以在业务代码的then里手动加状态校验,不符合预期就主动返回Promise.reject()抛错。
2. 优化Promise写法,避免回调地狱
不要嵌套写then,把内部Promise return出去做链式调用,保证所有环节的错误都能被最后一个catch捕获:
const formdata = new FormData(); formdata.append("file", image.file); api .post("/api/v1/file/upload", formdata) .then((response) => { // 这里可以加兜底状态校验 if (response.status !== 200) return Promise.reject(new Error("文件上传失败")) const imageUrl = response.data.url // 把内部请求的Promise return出去,透传到外层链式调用 return api.put(`/api/v1/radio/${id}`, { name: name, email: email, image: imageUrl, }) }) .then(response => { console.log("全流程执行成功", response); }) .catch(error => { console.log("流程异常:", error); })
更推荐用async/await写法,逻辑和同步代码一致,维护成本更低:
async function submitForm() { try { const formdata = new FormData(); formdata.append("file", image.file); const uploadRes = await api.post("/api/v1/file/upload", formdata); // 兜底校验上传结果 if (uploadRes.status !== 200) throw new Error("文件上传失败"); const imageUrl = uploadRes.data.url; const updateRes = await api.put(`/api/v1/radio/${id}`, { name: name, email: email, image: imageUrl, }); console.log("提交成功", updateRes); } catch (error) { console.log("提交失败:", error); } } // 调用函数执行逻辑 submitForm()
内容的提问来源于stack exchange,提问作者Pedro Lima
相关产品推荐
相关产品推荐

