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

news/2024/12/28 0:41:56/

在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 示例
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 提供的特定功能。


http://www.ppmy.cn/news/1558652.html

相关文章

Java 【数据结构】 哈希(Hash超详解)HashSetHashMap【神装】

登神长阶 第十神装 HashSet 第十一神装 HashMap 目录 &#x1f454;一.哈希 &#x1f9e5;1.概念 &#x1fa73;2.Object类的hashCode()方法: &#x1f45a;3.String类的哈希码: &#x1f460;4.注意事项: &#x1f3b7;二.哈希桶 &#x1fa97;1.哈希桶原理 &#x…

#渗透测试#漏洞挖掘#红蓝攻防#漏洞挖掘#未授权漏洞-Es未授权漏洞

免责声明 本教程仅为合法的教学目的而准备&#xff0c;严禁用于任何形式的违法犯罪活动及其他商业行为&#xff0c;在使用本教程前&#xff0c;您应确保该行为符合当地的法律法规&#xff0c;继续阅读即表示您需自行承担所有操作的后果&#xff0c;如有异议&#xff0c;请立即停…

Textual Dataset Distillation via Language Model Embedding

Method 将数据集丢入embedding模型&#xff0c;丢入embedding前可以加入prompt加强效果&#xff0c;然后获取k-means聚类的中心向量来作为需要的蒸馏embeddings&#xff0c;然后使用vec2text模型还原成原始文本。 Result Q&#xff1a; 这里有一点不清楚&#xff1a; 聚类中…

BAPI_BATCH_CHANGE在更新后不自动更新批次特征

1、问题介绍 在CL03中看到分类特性配置了制造日期字段&#xff0c;并绑定了生产日期字段MCH1~HSDAT MSC2N修改批次的生产日期字段时&#xff0c;自动修改了对应的批次特性 但是通过BAPI&#xff1a;BAPI_BATCH_CHANGE修改生产日期时&#xff0c;并没有更新到批次特性中 2、BAPI…

CSS系列(35)-- Subgrid详解

前端技术探索系列&#xff1a;CSS Subgrid详解 &#x1f4d0; 致读者&#xff1a;探索子网格布局的艺术 &#x1f44b; 前端开发者们&#xff0c; 今天我们将深入探讨 CSS Subgrid&#xff0c;这个强大的网格布局扩展特性。 基础概念 &#x1f680; 子网格设置 /* 父网格…

ubuntu编译遇到的问题

一.ffmpeg链接不到库文件 undefined reference to avcodec_register_all undefined reference to avcodec_register_all undefined reference to av_opt_set_defaults undefined reference to av_opt_set_defaults undefined reference to av_parse_video_frame_rate undefine…

MDS-NPV/NPIV

在存储区域网络&#xff08;SAN&#xff09;中&#xff0c;域ID&#xff08;Domain ID&#xff09;是一个用于区分不同存储区域的关键参数。域ID允许SAN环境中的不同部分独立操作&#xff0c;从而提高效率和安全性。以下是关于域ID的一些关键信息&#xff1a; 域ID的作用&…

C++线程安全函数

在 C 中&#xff0c;线程安全的函数是指在多线程环境下可以安全调用&#xff0c;不会导致数据竞争或其他并发问题的函数。C 标准库提供了许多线程安全的函数&#xff0c;同时也要求开发者在使用自定义函数时确保线程安全。以下是一些常见的线程安全函数和实现线程安全的方法&am…