常见原因是未等待请求完成就读取 responseText;XMLHttpRequest 默认异步,需监听 onload 或确保 readyState === 4 且 status ≥ 200 才安全读取,尤其注意 file:// 协议下 status 常为 0。
常见原因是没等请求完成就去读取 responseText。XMLHttpRequest 默认异步,send() 立即返回,但响应还没到。必须监听 onload 或检查 readyState === 4 且 status === 200 才安全读取。
onload 最简洁,它只在成功收到完整响应后触发onreadystatechange + readyState === 4,因为这时可能 status 是 0(本地文件或 CORS 失败)file:// 协议下多数浏览器会令 status === 0,即使内容已加载const xhr = new XMLHttpRequest();
xhr.open('GET', 'data.xml');
xhr.onload = function() {
if (xhr.status >= 200 && xhr.status < 300) {
console.log(xhr.responseText); // ✅ 安全
}
};
xhr.send();
responseText 是纯字符串,不能直接当 DOM 操作;必须用 responseXML 或手动解析。但 responseXML 只在响应头 Content-Type 包含 xml 且解析成功时才有效——否则为 null。
Content-Type: application/xml?responseXML 很可能为空
误(如未闭合标签),也会导致 responseXML === null
responseXML,失败则用 DOMParser 手动解析 responseText
xhr.onload = function() {
let doc;
if (xhr.responseXML && xhr.responseXML.documentElement) {
doc = xhr.responseXML;
} else {
const parser = new DOMParser();
doc = parser.parseFromString(xhr.responseText, 'application/xml');
}
const title = doc.querySelector('title')?.textContent;
};
如果后端期望接收原始 XML 文本(比如 SOAP 接口),必须显式设置 Content-Type: application/xml,否则服务器可能按 text/plain 解析而报错。
setRequestHeader() 设置,且必须在 open() 之后、send() 之前调用Document 对象;若用 XMLSerializer 序列化 DOM,结果仍是字符串utf-8,发送前确保字符串确实是 UTF-8 编码(现代浏览器 JS 字符串默认是 UTF-16,但 send(string) 会自动转 UTF-8)const xmlStr = ``; xhr.open('POST', '/api'); xhr.setRequestHeader('Content-Type', 'application/xml'); xhr.send(xmlStr); 123
没有被废弃,但新项目更推荐 fetch()。XMLHttpRequest 仍被所有浏览器完整支持,W3C 标准也未标记为过时;只是它 API 设计陈旧(回调嵌套、事件分散、不支持 Promise),而 fetch() 更简洁、可与 async/await 配合。
XMLHttpRequest.upload.onprogress 目前仍是唯一标准方案xhr.abort() 比 AbortController 在旧环境里更兼容withCredentials,但 fetch 的 credentials: 'include' 更直观真正容易被忽略的是:XMLHttpRequest 的错误边界比 fetch 更模糊——网络中断、DNS 失败、CORS 拒绝,有时都只触发 onerror,不提供具体原因。调试时得结合浏览器 Network 面板看真实状态码和响应头。