fetch 与 xmlHttpRequest 请求总结
文章目录
- fetch 、XMLHttpRequest、ajax 简要介绍
- fetch 与 xmlHttpRequest 比较
fetch 、XMLHttpRequest、ajax 简要介绍
- Fetch API
- 概述
- Fetch是一种现代的JavaScript API,用于在浏览器中进行网络请求。它提供了一种更灵活、更强大的方式来获取资源,相比传统的XMLHttpRequest具有更简洁的语法和更好的Promise集成。
- 请求参数和方法
- 基本语法:
fetch(url, options)
。其中url
是要请求的资源的URL地址,options
是一个可选的配置对象,用于配置请求的各种参数。 - 请求方法:在
options
对象中,可以通过method
属性设置请求方法,如GET
、POST
、PUT
、DELETE
等。例如:{method: 'POST'}
。 - 请求头:使用
headers
属性设置请求头。例如,设置Content - Type
为application/json
:{headers: {'Content - Type': 'application/json'}}
。 - 请求体:对于
POST
、PUT
等请求,可以通过body
属性发送请求体数据。如果是发送JSON数据,可以先将JavaScript对象转换为JSON字符串,如{body: JSON.stringify({key: 'value'})}
。
- 基本语法:
- 概述
- 应用实例
- 简单的GET
请求获取数据:
fetch('https://example.com/api/data')
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error(error));
POST
请求发送数据:
const dataToSend = {name: 'John', age: 30};
fetch('https://example.com/api/submit', {
method: 'POST',
headers: {'Content - Type': 'application/json'},
body: JSON.stringify(dataToSend)
})
.then(response => response.json())
.then(result => console.log(result))
.catch(error => console.error(error));
- 注意事项
- Fetch默认不会发送或接收cookies。如果需要发送cookies,需要在
options
对象中设置credentials
属性为'include'
。 - 当接收到的响应状态码不是
200 - 299
范围时,fetch
不会自动抛出错误。需要手动检查response.ok
属性来处理错误情况。例如:
- Fetch默认不会发送或接收cookies。如果需要发送cookies,需要在
fetch('https://example.com/api/data')
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
})
.then(data => console.log(data))
.catch(error => console.error(error));
- XMLHttpRequest(XHR)
- 概述
- XMLHttpRequest是一种较老的用于在JavaScript中进行HTTP请求的技术。它允许网页从服务器获取数据而无需刷新页面,是实现Ajax(Asynchronous JavaScript and XML)的核心对象。
- 请求参数和方法
- 创建对象:首先要创建一个
XMLHttpRequest
对象,如var xhr = new XMLHttpRequest();
。 - 打开请求:使用
open
方法来初始化一个请求,语法为xhr.open(method, url, async)
。其中method
是请求方法(如GET
、POST
等),url
是请求的URL,async
是一个布尔值,表示请求是否异步进行(通常为true
)。例如:xhr.open('GET', 'https://example.com/api/data', true);
。 - 设置请求头:通过
setRequestHeader
方法设置请求头。例如:xhr.setRequestHeader('Content - Type', 'application/json');
。 - 发送请求:使用
send
方法发送请求。对于GET
请求,一般不需要传递参数,即xhr.send(null)
;对于POST
请求,可以在send
方法中传递请求体数据,如xhr.send(JSON.stringify({key: 'value'}))
。
- 创建对象:首先要创建一个
- 应用实例
- 简单的
GET
请求:
- 简单的
- 概述
var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://example.com/api/data', true);
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
var data = JSON.parse(xhr.responseText);
console.log(data);
}
};
xhr.send(null);
- `POST`请求:
var xhr = new XMLHttpRequest();
xhr.open('POST', 'https://example.com/api/submit', true);
xhr.setRequestHeader('Content - Type', 'application/json');
var dataToSend = {name: 'John', age: 30};
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
var result = JSON.parse(xhr.responseText);
console.log(result);
}
};
xhr.send(JSON.stringify(dataToSend));
- 注意事项
- 由于
XMLHttpRequest
的事件驱动模型,需要注意readyState
属性的变化。readyState
的值从0到4,表示请求的不同阶段,当readyState
为4时,表示请求已完成。 - 跨域请求时,需要服务器端正确配置CORS(跨域资源共享),否则会出现跨域错误。
- 由于
- Ajax(Asynchronous JavaScript and XML)
- 概述
- Ajax不是一种新的技术,而是一种使用现有技术(如XMLHttpRequest或Fetch)实现的在网页中进行异步数据交互的模式。它允许网页在不刷新整个页面的情况下更新部分内容,提供了更好的用户体验。
- 请求参数和方法(使用XMLHttpRequest为例)
- 其请求参数和方法基本与
XMLHttpRequest
相同,因为XMLHttpRequest
是实现Ajax的主要方式之一。在Ajax模式下,重点是如何处理异步响应并更新页面内容。
- 其请求参数和方法基本与
- 应用实例
- 假设有一个网页,需要根据用户输入的城市名称获取天气信息并显示在页面上,而不刷新整个页面。可以这样实现:
- 概述
<!DOCTYPE html>
<html>
<head>
<title>Ajax Weather Example</title>
<script>
function getWeather() {
var city = document.getElementById('cityInput').value;
var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://api.example.com/weather?city=' + city, true);
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
var weatherData = JSON.parse(xhr.responseText);
document.getElementById('weatherResult').innerHTML = 'Temperature: ' + weatherData.temperature + ', Condition: ' + weatherData.condition;
}
};
xhr.send(null);
}
</script>
</head>
<body>
<input type="text" id="cityInput" placeholder="Enter city name">
<button onclick="getWeather()">Get Weather</button>
<div id="weatherResult"></div>
</body>
</html>
- 注意事项
- 性能方面,频繁的Ajax请求可能会影响性能,特别是在移动设备上。需要合理控制请求的频率和数据量。
- 安全性方面,要注意防范跨站脚本攻击(XSS)和跨域安全问题。在处理服务器返回的数据时,要进行适当的验证和过滤。同时,确保服务器正确配置CORS来处理跨域请求。
fetch 与 xmlHttpRequest 比较
- 性能对比
-
网络请求阶段
- 连接建立:
- XMLHttpRequest:在传统的XMLHttpRequest中,每次请求都需要经历完整的连接建立过程。例如,在低带宽环境下,建立新的TCP连接可能会引入一定的延迟。
- Fetch:它底层同样依赖于浏览器的网络请求机制,在连接建立方面没有本质上的性能优势,但由于其简洁的API设计,在一些复杂的网络请求场景下可能更容易优化。
- 请求发送和接收:
- XMLHttpRequest:它可以发送和接收各种类型的数据,但在处理复杂的数据格式转换(如JSON)时,可能需要额外的代码来处理响应数据。这可能会导致在数据处理阶段产生一些性能损耗。
- Fetch:它原生支持多种数据格式的处理,如
response.json()
、response.text()
和response.blob()
等方法,可以更方便地处理不同类型的数据。在数据接收阶段,对于JSON数据的处理,Fetch可以直接将其转换为JavaScript对象,相对高效。
- 连接建立:
-
异步处理模型
- XMLHttpRequest:采用事件驱动的异步处理模型,需要监听
readystatechange
事件来判断请求的状态。例如,在readyState
达到4(表示请求完成)且status
为200(表示成功)时才能处理响应数据。这种模型相对复杂,代码的可读性和维护性可能会受到影响,并且在处理多个请求时,容易出现状态混乱的情况。 - Fetch:基于Promise的异步处理方式使得代码结构更加清晰。通过
then()
和catch()
方法可以很方便地处理请求成功和失败的情况,并且多个Fetch请求可以方便地通过链式调用或者async/await
进行组合和顺序控制,减少了回调嵌套带来的性能损耗(如避免了“回调地狱”)。
- XMLHttpRequest:采用事件驱动的异步处理模型,需要监听
-
内存占用和资源管理
- XMLHttpRequest:在一些老旧的浏览器实现中,可能存在内存泄漏的风险,特别是在频繁创建和销毁XMLHttpRequest对象,或者处理大型响应数据时,如果没有正确地释放资源,可能会导致内存占用过高。
- Fetch:在现代浏览器中,Fetch API在资源管理方面相对较好。它能够更好地与浏览器的垃圾回收机制配合,并且在处理流数据(如部分加载大型文件)时,可以更灵活地控制内存占用,避免一次性加载过多的数据导致内存溢出。
-
应用对比
- 简单数据获取场景(如加载配置文件)
- XMLHttpRequest:
- 示例代码:
- XMLHttpRequest:
- 简单数据获取场景(如加载配置文件)
var xhr = new XMLHttpRequest();
xhr.open('GET', 'config.json', true);
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
var config = JSON.parse(xhr.responseText);
// 使用配置数据
}
};
xhr.send(null);
- 应用特点:在简单的数据获取场景下,XMLHttpRequest可以完成任务,但代码相对繁琐,需要关注
readyState
和status
的变化来处理响应。
- Fetch:
- 示例代码:
fetch('config.json')
.then(response => response.json())
.then(config => {
// 使用配置数据
})
.catch(error => console.error(error));
-
应用特点:使用Fetch的代码更加简洁明了,通过链式调用直接处理JSON数据,非常适合这种简单的异步数据获取场景,能够提高开发效率。
- 复杂数据交互场景(如表单提交和文件上传)
- XMLHttpRequest:
- 示例代码(以表单提交为例):
- XMLHttpRequest:
- 复杂数据交互场景(如表单提交和文件上传)
var form = document.getElementById('myForm');
var xhr = new XMLHttpRequest();
xhr.open('POST', 'submit.php', true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
var result = JSON.parse(xhr.responseText);
// 处理提交结果
}
};
form.addEventListener('submit', function (e) {
e.preventDefault();
var formData = new FormData(form);
var serializedData = '';
for (var pair of formData.entries()) {
serializedData += pair[0] + '=' + pair[1] + '&';
}
serializedData = serializedData.slice(0, -1);
xhr.send(serializedData);
});
- 应用特点:在复杂的数据交互场景下,XMLHttpRequest需要手动处理请求头、表单数据序列化等操作,并且要小心处理异步事件。代码的复杂性随着功能的增加而显著增加。
- Fetch:
- 示例代码(以表单提交为例):
var form = document.getElementById('myForm');
form.addEventListener('submit', function (e) {
e.preventDefault();
var formData = new FormData(form);
fetch('submit.php', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(result => {
// 处理提交结果
})
.catch(error => console.error(error));
});
-
应用特点:Fetch在处理复杂数据交互场景时,代码简洁性的优势更加明显。它可以直接使用
FormData
对象作为请求体,减少了数据处理的步骤,并且通过Promise的方式方便地处理响应。- 流数据处理场景(如实时数据推送或大型文件下载)
- XMLHttpRequest:
- 示例代码(以部分下载大型文件为例):
- XMLHttpRequest:
- 流数据处理场景(如实时数据推送或大型文件下载)
var xhr = new XMLHttpRequest();
xhr.open('GET', 'largeFile.zip', true);
xhr.onprogress = function (e) {
if (e.lengthComputable) {
var percentComplete = (e.loaded / e.total) * 100;
console.log(percentComplete + '% downloaded');
}
};
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
var fileData = xhr.response;
// 处理文件数据
}
};
xhr.send(null);
- 应用特点:XMLHttpRequest可以通过
onprogress
事件来监听文件下载的进度,但在处理流数据的细节方面(如如何高效地逐块处理数据)相对复杂,并且对于复杂的流数据应用场景(如实时数据推送的复杂业务逻辑)可能需要更多的自定义代码来实现。
- Fetch:
- 示例代码(以部分下载大型文件为例):
fetch('largeFile.zip')
.then(response => {
const reader = response.body.getReader();
let receivedLength = 0;
const contentLength = response.headers.get('Content-Length');
function readData() {
return reader.read().then(({ done, value }) => {
if (done) {
return;
}
receivedLength += value.length;
var percentComplete = (receivedLength / contentLength) * 100;
console.log(percentComplete + '% downloaded');
// 进一步处理数据块
if (receivedLength < contentLength) {
return readData();
}
});
}
return readData();
})
.catch(error => console.error(error));
- 应用特点:Fetch在流数据处理场景下,通过
ReadableStream
的相关API可以更方便地实现逐块处理数据的功能,并且在处理实时数据推送等场景时,其基于Promise的异步模型可以更好地与其他异步操作(如事件监听、数据转换等)相结合,提供更灵活的解决方案。