XMLHttpRequest(XHR)对象最全速查表(2025 版)
—— 虽然现在大家都用 fetch,但面试、老项目、理解底层原理时它仍然是王者!
| 项目 | 内容 / 写法(2025 推荐) | 必背度 |
|---|---|---|
| 创建对象 | const xhr = new XMLHttpRequest(); | ★★★★★ |
| 打开请求 | xhr.open(method, url, async=true, user=null, password=null) | ★★★★★ |
| 发送请求 | xhr.send(body)(GET 传 null 或省略,POST 传数据) | ★★★★★ |
| 监听状态变化 | xhr.onreadystatechange = function() { if (xhr.readyState === 4) { … } } | ★★★★ |
| 推荐监听方式(现代) | xhr.onload = () => { … } xhr.onerror = () => { … } | ★★★★★ |
| 超时设置 | xhr.timeout = 5000; xhr.ontimeout = () => { … } | ★★★★★ |
| 响应类型 | xhr.responseType = "json" | "text" | "document" | "blob" | "arraybuffer" | ★★★★★ |
| 取响应文本 | xhr.responseText(老项目) | ★★★★ |
| 取响应(推荐) | xhr.response(配合 responseType 使用,自动解析) | ★★★★★ |
| 状态码 | xhr.status(200、404、500 等) | ★★★★★ |
| 状态文本 | xhr.statusText(”OK”、”Not Found”) | ★★★★ |
| readyState 值 | 0=未初始化 1=OPENED 2=HEADERS_RECEIVED 3=LOADING 4=DONE | ★★★★★ |
2025 年最推荐的完整写法(直接复制用)
function xhrRequest({ method = "GET", url, data = null, timeout = 10000, responseType = "json" } = {}) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.responseType = responseType; // 关键!让 response 自动解析
xhr.timeout = timeout;
xhr.onload = () => {
if (xhr.status >= 200 && xhr.status < 300) {
resolve(xhr.response); // 自动是对象(json)或文本
} else {
reject(new Error(`HTTP ${xhr.status} ${xhr.statusText}`));
}
};
xhr.onerror = () => reject(new Error("网络错误"));
xhr.ontimeout = () => reject(new Error("请求超时"));
xhr.open(method, url, true); // async 永远 true
if (method === "POST" || method === "PUT") {
xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
}
xhr.send(data ? JSON.stringify(data) : null);
});
}
// 使用(和 fetch 几乎一样爽)
xhrRequest({ url: "/api/books" })
.then(data => console.log(data))
.catch(err => console.error(err));
xhrRequest({
method: "POST",
url: "/api/books",
data: { title: "三体" }
}).then(res => console.log("添加成功", res));
经典老写法(面试必会)
const xhr = new XMLHttpRequest();
xhr.open("GET", "books.xml", true);
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) { // 请求完成
if (xhr.status === 200) {
console.log(xhr.responseXML); // XML 文档
console.log(xhr.responseText); // 原始字符串
} else {
console.error("错误", xhr.status);
}
}
};
xhr.send(); // GET 不传参数
XHR vs Fetch 终极对比(2025 结论)
| 项目 | XMLHttpRequest | Fetch API(2025 推荐) |
|---|---|---|
| 是否 Promise | 否(要自己包) | 原生 Promise |
| 超时控制 | xhr.timeout(好用) | 需要 AbortController |
| 上传进度 | xhr.upload.onprogress(完美) | 支持,但写法稍复杂 |
| 响应类型自动解析 | xhr.response + responseType(好用) | res.json()、res.text() |
| 取消请求 | xhr.abort() | AbortController |
| 兼容性 | IE9+(包括 IE) | IE 全灭,现代浏览器 100% |
| 老项目/面试 | 必会 | 必会 |
| 新项目推荐 | 只在需要上传进度时用 | 99% 情况用 fetch |
2025 年最终结论(一句话记住)
- 新项目:99% 用
fetch或axios - 必须用 XHR 的 3 个场景:
- 需要上传/下载进度条(
xhr.upload.onprogress) - 老项目维护(IE、企业内网)
- 面试被问底层原理
背会上面那段 Promise 封装的 xhrRequest 函数 + 经典老写法,
你就已经完全掌握了 XMLHttpRequest,面试、企业项目、底层原理三不误!
需要我给你一个「XHR + Fetch + Axios 三套代码实时对比演示页面」,随时说一声~