🌐 第十一章:网络请求与数据交互

掌握现代网络请求的方法和数据处理技巧

11.1 Fetch API 详解

Fetch API 是现代浏览器提供的网络请求接口,替代了传统的 XMLHttpRequest。

基本用法

// 基本 GET 请求
async function fetchData() {
    try {
        const response = await fetch('https://api.example.com/data');
        
        if (!response.ok) {
            throw new Error(`HTTP error! status: ${response.status}`);
        }
        
        const data = await response.json();
        console.log(data);
    } catch (error) {
        console.error('Fetch error:', error);
    }
}

POST 请求

// POST 请求
async function postData() {
    try {
        const response = await fetch('https://api.example.com/data', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({
                name: 'John',
                age: 30
            })
        });
        
        const data = await response.json();
        console.log(data);
    } catch (error) {
        console.error('Fetch error:', error);
    }
}

11.2 处理 JSON、FormData、Blob

处理 JSON

// 解析 JSON
const response = await fetch('https://api.example.com/data');
const data = await response.json();

处理 FormData

// 发送 FormData
const formData = new FormData();
formData.append('name', 'John');
formData.append('age', 30);

const response = await fetch('https://api.example.com/upload', {
    method: 'POST',
    body: formData
});

处理 Blob

// 下载文件
const response = await fetch('https://example.com/image.jpg');
const blob = await response.blob();

// 创建下载链接
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'image.jpg';
document.body.appendChild(a);
a.click();
URL.revokeObjectURL(url);

11.3 AbortController

AbortController 用于取消正在进行的网络请求。
// 使用 AbortController
const controller = new AbortController();
const signal = controller.signal;

// 发起请求
const fetchPromise = fetch('https://api.example.com/data', {
    signal
});

// 取消请求
setTimeout(() => {
    controller.abort();
}, 1000);

// 处理结果
try {
    const response = await fetchPromise;
    const data = await response.json();
    console.log(data);
} catch (error) {
    if (error.name === 'AbortError') {
        console.log('Request aborted');
    } else {
        console.error(error);
    }
}

11.4 拦截器与封装思路

// 封装 Fetch API
class Http {
    constructor() {
        this.baseURL = 'https://api.example.com';
        this.headers = {
            'Content-Type': 'application/json'
        };
    }
    
    // 请求拦截器
    request(config) {
        // 添加认证 token
        const token = localStorage.getItem('token');
        if (token) {
            this.headers['Authorization'] = `Bearer ${token}`;
        }
        
        return {
            url: this.baseURL + config.url,
            method: config.method || 'GET',
            headers: { ...this.headers, ...config.headers },
            body: config.body
        };
    }
    
    // 响应拦截器
    response(response) {
        if (!response.ok) {
            throw new Error(`HTTP error! status: ${response.status}`);
        }
        return response.json();
    }
    
    // 发送请求
    async fetch(config) {
        try {
            const options = this.request(config);
            const response = await window.fetch(options.url, options);
            return await this.response(response);
        } catch (error) {
            console.error('Fetch error:', error);
            throw error;
        }
    }
    
    // 便捷方法
    get(url, config = {}) {
        return this.fetch({ ...config, url, method: 'GET' });
    }
    
    post(url, data, config = {}) {
        return this.fetch({
            ...config,
            url,
            method: 'POST',
            body: JSON.stringify(data)
        });
    }
}

// 使用
const http = new Http();
http.get('/data').then(data => {
    console.log(data);
});

动手练习

练习 1:基本 Fetch 请求

  1. 使用 Fetch API 发送 GET 请求
  2. 处理响应数据
  3. 添加错误处理

练习 2:POST 请求

  1. 使用 Fetch API 发送 POST 请求
  2. 发送 JSON 数据
  3. 发送 FormData

练习 3:AbortController

  1. 创建 AbortController
  2. 发送带 signal 的请求
  3. 测试取消请求

练习 4:封装 Fetch

  1. 创建一个 HTTP 类
  2. 添加请求和响应拦截器
  3. 实现 get 和 post 方法
  4. 测试封装后的 API