详细对比JS中XMLHttpRequest和fetch的使用

在JavaScript中,XMLHttpRequestfetch 是两种用于进行 HTTP 请求的 API。它们的主要区别在于设计理念、用法和功能支持。以下是两者的详细对比:


1. 语法与用法

  • XMLHttpRequest:

    • 较老的 API,最早出现在 2000 年代。
    • 支持异步和同步请求,但语法较为复杂。
    • 使用回调函数来处理异步结果。
  • fetch:

    • 于 ES6 引入,是现代浏览器提供的全新 API。
    • 基于 Promise,语法更简洁且更符合异步处理的标准(async/await)。
    • 更适合链式操作和流式处理。

2. 特点对比

特性 XMLHttpRequest fetch
支持的规范 基于 XMLHttpRequest 规范 基于 Fetch API 规范
异步编程 回调函数 Promise / async-await
流式响应处理 不支持 支持,通过 response.body
跨域支持(CORS) 需要设置额外头信息 默认支持
进度事件(onprogress) 支持 不直接支持
请求取消 通过 abort() 实现 通过 AbortController 实现
错误处理 错误不直接抛出(需手动检查状态码) 自动抛出网络级错误
文件上传 支持(FormData) 支持(FormData)

3. 代码对比

(1)XMLHttpRequest 示例
javascript 复制代码
function getDataWithXHR(url) {
    return new Promise((resolve, reject) => {
        const xhr = new XMLHttpRequest();
        xhr.open("GET", url, true); // 异步请求
        xhr.onreadystatechange = function () {
            if (xhr.readyState === 4) { // 请求完成
                if (xhr.status >= 200 && xhr.status < 300) {
                    resolve(xhr.responseText); // 返回数据
                } else {
                    reject(new Error(`Error: ${xhr.status}`));
                }
            }
        };
        xhr.onerror = function () {
            reject(new Error("Network Error"));
        };
        xhr.send();
    });
}

// 使用
getDataWithXHR("https://jsonplaceholder.typicode.com/posts/1")
    .then(data => console.log(data))
    .catch(error => console.error(error));
(2)fetch 示例
javascript 复制代码
async function getDataWithFetch(url) {
    try {
        const response = await fetch(url);
        if (!response.ok) {
            throw new Error(`HTTP error! status: ${response.status}`);
        }
        const data = await response.json(); // 解析 JSON 数据
        console.log(data);
    } catch (error) {
        console.error(error);
    }
}

// 使用
getDataWithFetch("https://jsonplaceholder.typicode.com/posts/1");

4. 功能对比

(1)进度事件支持
  • XMLHttpRequest 支持通过 onprogress 事件监听下载进度:
javascript 复制代码
const xhr = new XMLHttpRequest();
xhr.open("GET", "https://jsonplaceholder.typicode.com/posts", true);
xhr.onprogress = function (event) {
    console.log(`Loaded ${event.loaded} of ${event.total}`);
};
xhr.onload = function () {
    console.log(xhr.responseText);
};
xhr.send();
  • fetch 没有内置支持,需要结合 ReadableStream 实现:
javascript 复制代码
async function fetchWithProgress(url) {
    const response = await fetch(url);
    const reader = response.body.getReader();
    const contentLength = response.headers.get("Content-Length");

    let receivedLength = 0;
    const chunks = [];
    while (true) {
        const { done, value } = await reader.read();
        if (done) break;

        chunks.push(value);
        receivedLength += value.length;
        console.log(`Received ${receivedLength} of ${contentLength}`);
    }

    const decoder = new TextDecoder("utf-8");
    const fullText = decoder.decode(new Blob(chunks));
    console.log(fullText);
}

fetchWithProgress("https://jsonplaceholder.typicode.com/posts");

5. 请求取消

  • XMLHttpRequest 使用 abort() 方法:
javascript 复制代码
const xhr = new XMLHttpRequest();
xhr.open("GET", "https://jsonplaceholder.typicode.com/posts");
xhr.send();

setTimeout(() => {
    xhr.abort();
    console.log("Request canceled");
}, 1000);
  • fetch 使用 AbortController
javascript 复制代码
const controller = new AbortController();
const signal = controller.signal;

fetch("https://jsonplaceholder.typicode.com/posts", { signal })
    .then(response => response.json())
    .then(data => console.log(data))
    .catch(error => {
        if (error.name === "AbortError") {
            console.log("Request canceled");
        } else {
            console.error(error);
        }
    });

// 取消请求
setTimeout(() => controller.abort(), 1000);

6. 总结

  • 选择 XMLHttpRequest 的场景

    • 需要兼容非常旧的浏览器。
    • 需要监听进度事件。
  • 选择 fetch 的场景

    • 开发现代 Web 应用。
    • 需要更简单的语法和更强的功能(如流式处理)。

现代开发中,推荐优先使用 fetch,除非你需要使用 XMLHttpRequest 提供的特定功能。

相关推荐
JuneXcy7 分钟前
11.Layout-Pinia优化重复请求
前端·javascript·css
玉树临风江流儿12 分钟前
QT收费情况
开发语言·qt
天下无贼!17 分钟前
【自制组件库】从零到一实现属于自己的 Vue3 组件库!!!
前端·javascript·vue.js·ui·架构·scss
ankleless29 分钟前
C语言(02)——标准库函数大全(持续更新)
c语言·开发语言·算法·标准库函数·零基础自学
PineappleCoder1 小时前
JS 作用域链拆解:变量查找的 “俄罗斯套娃” 规则
前端·javascript·面试
知识分享小能手1 小时前
Vue3 学习教程,从入门到精通,Vue3 中使用 Axios 进行 Ajax 请求的语法知识点与案例代码(23)
前端·javascript·vue.js·学习·ajax·vue·vue3
凹凸曼说我是怪兽y1 小时前
python后端之DRF框架(上篇)
开发语言·后端·python
533_1 小时前
[echarts] 更新数据
前端·javascript·echarts
l1t1 小时前
修改DeepSeek翻译得不对的V语言字符串文本排序程序
c语言·开发语言·python·v语言
讨厌吃蛋黄酥1 小时前
利用Mock实现前后端联调的解决方案
前端·javascript·后端