全部学科
Python全栈
python
NodeJS全栈
nodejs
小程序首页
📅 2026-05-17 12 分钟 ✍️ juanwangdev

网络请求与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'  // 不发送
});

要点总结

  1. response.ok:检查200-299状态码
  2. 响应体一次性:只能读取一次,不能重复
  3. AbortController:取消请求和超时处理
  4. 错误区分:response.ok检查HTTP错误,catch捕获网络错误
  5. credentials:跨域Cookie需设置include

📝 发现内容有误?点击此处直接编辑

← 上一篇 浏览器BOM与窗口对象
下一篇 → HTML figure与details语义化标签
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库