当前位置: 首页 > article >正文

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

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


1. 语法与用法

  • XMLHttpRequest:

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

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

2. 特点对比

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

3. 代码对比

(1)XMLHttpRequest 示例
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 示例
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 事件监听下载进度:
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 实现:
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() 方法:
const xhr = new XMLHttpRequest();
xhr.open("GET", "https://jsonplaceholder.typicode.com/posts");
xhr.send();

setTimeout(() => {
    xhr.abort();
    console.log("Request canceled");
}, 1000);
  • fetch 使用 AbortController
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 提供的特定功能。


http://www.kler.cn/a/455224.html

相关文章:

  • 【开发问题记录】执行 git cz 报require() of ES Module…… 错误
  • 内置ALC的前置放大器D2538A/D3308
  • 一个服务器可以搭建几个网站?搭建一个网站的流程介绍
  • Rocky DEM tutorial7_Conical Dryer_锥形干燥器
  • Linux | 零基础Ubuntu卸载MySQL Server 零痕迹
  • 支持selenium的chrome driver更新到131.0.6778.204
  • 吴恩达深度学习-第一周作业-题目
  • 结构方程模型【SEM】:非线性、非正态、交互作用及分类变量分析
  • 【人工智能学习】线性回归模型使用Python实现简单的线性回归
  • 我们来学mysql -- 区分大写
  • 王佩丰24节Excel学习笔记——第十八讲:Lookup和数组
  • C++ 的IO流(标准IO流 和文件IO流)
  • css 样式隐形
  • python如何使用RSA加密,避免明文密码
  • Centos7.9自动封禁IP
  • 基于 Python Django 的农产品销售系统的研究与实现
  • IEC103 转 ModbusTCP 网关(三格电子)
  • 网络游戏多开有IP限制问题如何解决
  • 粮油与饲料科技杂志社粮油与饲料科技编辑部粮油与饲料科技杂志2024年第7期目录
  • 代码随想录算法训练营第三十五天|01背包问题 二维和一维(卡码网第46题)、416分割等和子集