详细对比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 提供的特定功能。

相关推荐
明月_清风22 分钟前
自定义右键菜单:在项目里实现“选中文字即刻生成新提示”
前端·javascript
明月_清风23 分钟前
告别后端转换:高质量批量导出实战
前端·javascript
刘发财5 小时前
弃用html2pdf.js,这个html转pdf方案能力是它的几十倍
前端·javascript·github
ssshooter12 小时前
看完就懂 useSyncExternalStore
前端·javascript·react.js
Live0000013 小时前
在鸿蒙中使用 Repeat 渲染嵌套列表,修改内层列表的一个元素,页面不会更新
前端·javascript·react native
柳杉13 小时前
使用Ai从零开发智慧水利态势感知大屏(开源)
前端·javascript·数据可视化
球球pick小樱花14 小时前
游戏官网前端工具库:海内外案例解析
前端·javascript·css
喝水的长颈鹿14 小时前
【大白话前端 02】网页从解析到绘制的全流程
前端·javascript
用户145369814587814 小时前
VersionCheck.js - 让前端版本更新变得简单优雅
前端·javascript
codingWhat14 小时前
整理「祖传」代码,就是在开发脚手架?
前端·javascript·node.js