You need to enable JavaScript to run this app. 为何XMLHttpRequest.onreadystatechange可返回status而onload不行,二者如何选择
优惠活动
大模型
产品
解决方案
定价
更多

为何XMLHttpRequest.onreadystatechange可返回status而onload不行,二者如何选择

XMLHttpRequest 事件触发逻辑及使用建议

1. 为什么onload没有触发错误处理

onload 事件的触发前提是请求完整完成了HTTP收发流程,也就是客户端已经收到了服务端返回的完整响应(无论状态码是200还是404、500)。
你遇到的无反馈情况,是因为错误出现在HTTP响应生成之前:比如DNS解析失败、跨域请求被拦截、网络断开、目标地址完全不可达等,这类场景下客户端根本没收到任何有效HTTP响应,onload 不会触发,此时触发的是onerror事件,你没有监听该事件所以没有任何反馈。
补充:如果是404、500这类HTTP级别的错误,onload 是会正常触发的,你原本写的状态码判断逻辑可以正常工作。

2. 为什么onreadystatechange会触发两次错误

onreadystatechange 事件会在readyState(请求状态)每一次变化时都触发,正常请求的readyState会从0依次变到4:

  • readyState = 2:已收到响应头
  • readyState = 3:响应体加载中
  • readyState = 4:响应全部加载完成
    你没有在事件逻辑里加if (this.readyState === 4)的判断,所以当readyState变为2时,已经可以读取到status状态码,满足非200的条件就会报一次错;等readyState变为4时又会再执行一次逻辑,所以一共报错两次。

3. 二者如何选择,onload的正确使用方式

优先选onload,它是XMLHttpRequest 2.0标准新增的简化接口,默认对应readyState === 4的场景,不需要手动判断请求状态,逻辑更清晰,完全符合你的使用偏好。
你只需要补全缺失的异常事件监听即可覆盖所有错误场景,以下是修改后的可运行代码:

<!DOCTYPE html>
<html>
  <head>
    <title>XMLHttpRequest</title>
  </head>
  <body>
    <script>
      var request = new XMLHttpRequest();
      // 请求成功完成(收到完整HTTP响应,无论状态码)
      request.onload = function(){
        // 不要只判断等于200,所有2xx状态码都属于请求成功
        if(this.status >= 200 && this.status < 300){
          document.getElementById("stat").innerHTML = this.status;
          document.getElementById("size").innerHTML = this.response.length;
          document.getElementById("data").innerHTML = JSON.parse(this.response);
        }else{
          console.log("HTTP错误: " + this.status);
        }
      }
      // 网络层面错误(无响应返回)
      request.onerror = function(){
        console.log("网络错误,请求失败,状态码:" + this.status); // 该场景下status固定为0
      }
      // 可选:监听请求被主动取消的场景
      request.onabort = function(){
        console.log("请求已被取消");
      }
      request.open('GET','https://hplussport.com/api/products');
      request.send();
    </script>
    <div>
      Response Data<br/>
      Status: <span id="stat">Loading...</span><br/>
      Size  : <span id="size">Loading...</span> bytes<br/>
      Data  : <span id="data">Loading...</span>
    </div>
  </body>
</html>

内容的提问来源于stack exchange,提问作者MrMills

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.21 13:36:08