浏览器 Fetch API 详解
Fetch API 是现代浏览器提供的用于发起网络请求的接口,它基于 Promise 实现,替代了传统的 XMLHttpRequest
,提供了更强大、更灵活的功能。
1. 基本用法
使用 fetch()
函数发起请求,返回一个 Promise:
fetch('https://api.example.com/data')
.then(response => {
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
return response.json(); // 解析为 JSON
})
.then(data => console.log(data))
.catch(error => console.error('Fetch error:', error));
2. 请求参数
fetch()
接受第二个可选参数 init
,用于配置请求:
fetch('https://api.example.com/posts', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer token123'
},
body: JSON.stringify({ title: 'New Post', content: 'Hello World' }),
mode: 'cors', // 跨域模式
credentials: 'include', // 携带 cookies
cache: 'no-cache', // 缓存策略
redirect: 'follow', // 重定向处理
})
.then(res => res.json())
.then(data => console.log(data));
3. 响应处理
响应对象包含多种解析方法:
fetch('https://example.com/data')
.then(res => {
res.text(); // 解析为文本
res.json(); // 解析为 JSON
res.blob(); // 解析为二进制文件
res.arrayBuffer(); // 解析为二进制数组
res.formData(); // 解析为表单数据
});
4. 处理不同类型的请求
GET 请求(带查询参数):
const query = new URLSearchParams({ page: 1, limit: 10 });
fetch(`https://api.example.com/users?${query}`);
POST 请求(表单数据):
const formData = new FormData();
formData.append('file', fileInput.files[0]);
formData.append('name', 'example');
fetch('https://api.example.com/upload', {
method: 'POST',
body: formData // 无需设置 Content-Type,浏览器会自动处理
});
5. 错误处理
- HTTP 错误(如 404、500)不会触发
catch
,需手动检查response.ok
- 网络错误(如断网)才会触发
catch
fetch('https://nonexistent-api.com')
.then(res => {
if (!res.ok) {
throw new Error(`HTTP error! Status: ${res.status}`);
}
return res.json();
})
.catch(err => console.error('Network error:', err));
6. 中止请求
使用 AbortController
中止未完成的请求:
const controller = new AbortController();
const signal = controller.signal;
fetch('https://api.example.com/large-data', { signal })
.then(res => res.json())
.catch(err => {
if (err.name === 'AbortError') {
console.log('Request aborted');
}
});
// 5秒后中止请求
setTimeout(() => controller.abort(), 5000);
7. 自定义请求头
fetch('https://api.example.com', {
headers: {
'X-Custom-Header': 'value',
'Accept': 'application/json'
}
});
8. 并发请求
使用 Promise.all
并发处理多个请求:
Promise.all([
fetch('https://api.example.com/data1'),
fetch('https://api.example.com/data2')
])
.then(responses => Promise.all(responses.map(res => res.json())))
.then(data => console.log(data));
9. 与 XMLHttpRequest 的对比
特性 | Fetch API | XMLHttpRequest |
---|---|---|
接口类型 | Promise 驱动 | 事件驱动 |
语法复杂度 | 更简洁 | 更繁琐 |
流式响应处理 | 支持(通过 body.getReader() ) | 不支持 |
跨域支持 | 原生支持 CORS | 需要额外配置 |
中止请求 | 通过 AbortController | 通过 abort() 方法 |
进度监听 | 需要手动实现 | 内置 onprogress 事件 |
Fetch API 提供了更现代化、更优雅的方式来处理网络请求,尤其适合配合 async/await
使用:
Node.js 中,fetch
API
在 Node.js 中,fetch
API 从 Node.js v17.5 开始得到了原生支持,并且从 Node.js v18 开始被更广泛地推荐使用。这使得你可以在服务器端直接使用与浏览器环境中相同的 Fetch API 来发起 HTTP 请求,而无需依赖第三方库如 node-fetch
或 axios
。
基本用法
fetch()
函数的基本形式如下:
fetch(resource, init)
resource
: 要请求的资源 URL。init
: 可选参数,一个配置对象,用于设置请求方法、headers、body 等。
返回一个 Promise
,该 Promise
解析为 Response
对象。
Response 对象
Response
对象提供了处理响应的方法,比如 .json()
, .text()
, .blob()
, 和 .arrayBuffer()
等,这些方法都返回一个 Promise
。
示例:GET 请求
下面是一个简单的例子,演示如何从 GitHub API 获取用户信息:
async function fetchGitHubUserInfo(username) {
const url = `https://api.github.com/users/${username}`;
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
const data = await response.json();
console.log(data);
} catch (error) {
console.error('Error fetching GitHub user info:', error.message);
}
}
fetchGitHubUserInfo('octocat');
发起 POST 请求
当你需要发送数据到服务器时,可以使用 POST 方法:
async function postData(url = '', data = {}) {
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
});
return response.json(); // 解析 JSON 数据
}
postData('https://jsonplaceholder.typicode.com/posts', {
title: 'foo',
body: 'bar',
userId: 1
}).then(data => console.log(data));
使用 Headers
你可以通过 Headers
接口来创建和修改 HTTP 头部信息:
const headers = new Headers({
'Authorization': 'Bearer your-token-here',
'Accept': 'application/json'
});
fetch('https://api.example.com/data', { headers })
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
注意事项
-
错误处理:
fetch()
只有在网络故障或请求被阻止的情况下才会拒绝 Promise。即使 HTTP 状态码不是成功的(如404或500),它仍然会解析成功。因此,检查response.ok
是很重要的。 -
Node.js 版本: 确保你的 Node.js 版本是 v17.5 或更高版本以获得对
fetch
的最佳支持。对于旧版本,你可能需要安装并使用像node-fetch
这样的包。 -
AbortController: 支持取消请求,可以通过
AbortController
实现。 -
默认行为: 默认情况下,
fetch
不会在跨域请求中发送凭据(cookies)。如果需要,你可以通过设置credentials
属性来改变这一点。
以上就是关于在 Node.js 中使用 fetch
API 的基本介绍和示例。fetch
提供了一种现代且强大的方式来发出网络请求,其灵活性和易用性使其成为许多开发者首选的 HTTP 客户端解决方案。
Node.js 对 Promise 的支持历程及与浏览器的对比:
1. 支持时间线
-
ES6 (ES2015) 基础支持:
Node.js 从 v4.0.0 (2015 年 9 月) 开始支持原生 Promise,与 ES6 标准保持一致。此时可使用new Promise()
构造函数及基本方法(.then()
、.catch()
、.finally()
)。 -
Promise 全局对象:
Node.js 从 v8.0.0 (2017 年 5 月) 开始完全支持Promise.all()
、Promise.race()
等静态方法,与现代浏览器一致。 -
内置 API 的 Promise 化:
Node.js 在 v10.0.0 (2018 年 4 月) 引入util.promisify
,方便将回调式 API 转为 Promise 风格;
v14.0.0 (2020 年 4 月) 后,核心模块(如fs
、child_process
)全面支持 Promise 版本(如fs/promises
)。
promise介绍 参考前端第六章 6.es新特性Promise-CSDN博客