React.js中如何捕获net::ERR_CONNECTION_TIMED_OUT错误并展示给用户
问题解答
现有代码的核心问题
- 外层同步
try/catch完全无效:Axios.post是异步Promise操作,同步try/catch只能捕获同调用栈的同步错误,无法捕获异步Promise抛出的异常,这个外层块可以直接删除。 - Promise的catch分支判断逻辑不全:Axios抛出的错误分为三类,你只处理了服务端返回响应的场景:
- 服务端返回非2xx状态码:存在
error.response,就是你现在处理的场景 - 请求发出但未收到响应:包括你遇到的
net::ERR_CONNECTION_TIMED_OUT、网络断开、跨域拦截等,这种场景只有error.request,没有error.response - 请求配置错误:请求发送前就触发的普通错误,既没有
error.response也没有error.request
所以你现在的代码会漏掉超时、断网这类错误,不会触发setError,自然无法展示给用户。
- 服务端返回非2xx状态码:存在
修正方案
方案1:保持Promise链式写法
直接调整catch分支的逻辑即可:
const [error, setError] = useState(""); Axios.post('http://10.20.2.3:5000/accounts/login', { email, password }).then(response =>{ if (response.status === 201) { history.push("/admin/dashboard"); } }).catch(error => { let errorMsg = "未知错误"; if (error.response) { errorMsg = error.response.data.message; } else if (error.request) { // 处理超时、断网类错误 errorMsg = "网络连接超时,请检查网络或稍后重试"; } else { errorMsg = error.message; } setError(errorMsg); setLoading(false); }); // isOpen判断用!!error更严谨 <Alert color="danger" isOpen={!!error} fade={true}> { error } </Alert>
方案2:改用async/await写法,就可以正常使用try/catch
这种写法逻辑更清晰,更适合新手理解:
const [error, setError] = useState(""); const handleLogin = async () => { setLoading(true); setError(""); try { const response = await Axios.post('http://10.20.2.3:5000/accounts/login', { email, password }); if (response.status === 201) { history.push("/admin/dashboard"); } } catch (error) { let errorMsg = "未知错误"; if (error.response) { errorMsg = error.response.data.message; } else if (error.request) { errorMsg = "网络连接超时,请检查网络或稍后重试"; } else { errorMsg = error.message; } setError(errorMsg); } finally { setLoading(false); } } <Alert color="danger" isOpen={!!error} fade={true}> { error } </Alert>
额外注意点
- 判断相等尽量用
===代替==,避免隐式类型转换导致的逻辑bug - 无论请求成功失败都要记得重置
loading状态,上面的方案里用了finally统一处理,逻辑更稳妥
内容的提问来源于stack exchange,提问作者Boidurja Talukdar
相关产品推荐
相关产品推荐

