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

相关推荐
q567315232 分钟前
R语言初学者爬虫简单模板
开发语言·爬虫·r语言·iphone
rzl021 小时前
java web5(黑马)
java·开发语言·前端
Amy.Wang1 小时前
前端如何实现电子签名
前端·javascript·html5
时序数据说1 小时前
为什么时序数据库IoTDB选择Java作为开发语言
java·大数据·开发语言·数据库·物联网·时序数据库·iotdb
海天胜景1 小时前
vue3 el-table 行筛选 设置为单选
javascript·vue.js·elementui
今天又在摸鱼1 小时前
Vue3-组件化-Vue核心思想之一
前端·javascript·vue.js
百锦再1 小时前
Vue中对象赋值问题:对象引用被保留,仅部分属性被覆盖
前端·javascript·vue.js·vue·web·reactive·ref
jingling5551 小时前
面试版-前端开发核心知识
开发语言·前端·javascript·vue.js·面试·前端框架
FogLetter1 小时前
图片懒加载:让网页飞起来的魔法技巧 ✨
前端·javascript·css
拾光拾趣录1 小时前
JavaScript 加载对浏览器渲染的影响
前端·javascript·浏览器