网络请求与Fetch API
Fetch API提供了现代、灵活的网络请求方式,替代传统XMLHttpRequest。
基本用法
GET请求
JavaScript
// 基本GET请求
fetch('https://api.example.com/data')
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error(error));
// 使用async/await
async function getData() {
try {
const response = await fetch('https://api.example.com/data');
const data = await response.json();
console.log(data);
} catch (error) {
console.error(error);
}
}
POST请求
JavaScript
// POST请求
fetch('https://api.example.com/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ name: '张三', age: 25 })
})
.then(response => response.json())
.then(data => console.log(data));
// async/await版本
async function createUser(user) {
const response = await fetch('https://api.example.com/users', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(user)
});
return response.json();
}
请求配置
method方法
JavaScript
// HTTP方法
method: 'GET' // 获取
method: 'POST' // 创建
method: 'PUT' // 更新(整体)
method: 'PATCH' // 更新(部分)
method: 'DELETE' // 删除
headers请求头
JavaScript
fetch('https://api.example.com/data', {
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer token123',
'Accept': 'application/json'
}
});
body请求体
JavaScript
// JSON数据
body: JSON.stringify({ name: '张三' })
// FormData(文件上传)
const formData = new FormData();
formData.append('file', fileInput.files[0]);
formData.append('name', '张三');
fetch('https://api.example.com/upload', {
method: 'POST',
body: formData // 不需设置Content-Type
});
// URLSearchParams
const params = new URLSearchParams({ name: '张三', age: 25 });
fetch('https://api.example.com/data', {
method: 'POST',
body: params
});
响应处理
Response对象属性
JavaScript
const response = await fetch('https://api.example.com/data');
response.ok; // true (200-299)
response.status; // 200
response.statusText; // 'OK'
response.headers; // 响应头
response.url; // 实际URL
response.redirected; // 是否重定向
响应体读取方法
JavaScript
// JSON格式
const data = await response.json();
// 文本格式
const text = await response.text();
// Blob格式(文件下载)
const blob = await response.blob();
// ArrayBuffer格式
const buffer = await response.arrayBuffer();
// FormData格式
const formData = await response.formData();
// 注意:响应体只能读取一次
处理不同响应类型
JavaScript
async function handleResponse(response) {
const contentType = response.headers.get('Content-Type');
if (contentType.includes('application/json')) {
return response.json();
} else if (contentType.includes('text/')) {
return response.text();
} else if (contentType.includes('image/')) {
return response.blob();
}
}
错误处理
检查响应状态
JavaScript
async function fetchData() {
try {
const response = await fetch('https://api.example.com/data');
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const data = await response.json();
return data;
} catch (error) {
console.error('请求失败:', error.message);
}
}
网络错误处理
JavaScript
fetch('https://api.example.com/data')
.then(response => {
if (!response.ok) {
// 服务器响应错误
throw new Error(`Status: ${response.status}`);
}
return response.json();
})
.catch(error => {
if (error.name === 'TypeError') {
// 网络错误(无法连接)
console.error('网络错误');
} else {
console.error(error.message);
}
});
请求取消
AbortController
JavaScript
const controller = new AbortController();
const signal = controller.signal;
fetch('https://api.example.com/data', { signal })
.then(response => response.json())
.then(data => console.log(data))
.catch(error => {
if (error.name === 'AbortError') {
console.log('请求已取消');
}
});
// 取消请求
controller.abort();
超时处理
JavaScript
function fetchWithTimeout(url, timeout = 5000) {
const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), timeout);
return fetch(url, { signal: controller.signal })
.finally(() => clearTimeout(timer));
}
fetchWithTimeout('https://api.example.com/data', 3000)
.then(response => response.json())
.catch(error => {
if (error.name === 'AbortError') {
console.error('请求超时');
}
});
并发请求
Promise.all
JavaScript
// 并发请求
const [users, products] = await Promise.all([
fetch('https://api.example.com/users').then(r => r.json()),
fetch('https://api.example.com/products').then(r => r.json())
]);
Promise.allSettled
JavaScript
// 所有请求完成(无论成功失败)
const results = await Promise.allSettled([
fetch('https://api.example.com/users'),
fetch('https://api.example.com/products')
]);
results.forEach(result => {
if (result.status === 'fulfilled') {
console.log('成功', result.value);
} else {
console.log('失败', result.reason);
}
});
CORS跨域
跨域请求模式
JavaScript
// 跨域请求(需服务器支持CORS)
fetch('https://other-domain.com/api/data')
.then(response => response.json());
// 设置模式
fetch('https://api.example.com/data', {
mode: 'cors' // 跨域(默认)
// mode: 'no-cors' // 不透明请求(受限)
// mode: 'same-origin' // 同源请求
});
credentials凭证
JavaScript
// 发送Cookie
fetch('https://api.example.com/data', {
credentials: 'include' // 发送跨域Cookie
// credentials: 'same-origin' // 同源发送(默认)
// credentials: 'omit' // 不发送
});
要点总结
- response.ok:检查200-299状态码
- 响应体一次性:只能读取一次,不能重复
- AbortController:取消请求和超时处理
- 错误区分:response.ok检查HTTP错误,catch捕获网络错误
- credentials:跨域Cookie需设置include
📝 发现内容有误?点击此处直接编辑