Fetch API 完全教程

第一章:Fetch API 基础

1.1 基本用法

Fetch API 的基本使用方法。

练习 1.1:基本请求示例

展示 Fetch API 的基本请求方法。

基本请求示例
// GET 请求
fetch('https://api.example.com/data')
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error('Error:', error));

// POST 请求
fetch('https://api.example.com/data', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    name: 'John',
    age: 30
  })
})
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error('Error:', error));

1.2 请求配置

Fetch API 的请求配置选项。

练习 1.2:请求配置示例

展示请求配置的使用。

请求配置示例
// 完整的请求配置
fetch('https://api.example.com/data', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Bearer token'
  },
  body: JSON.stringify({
    name: 'John',
    age: 30
  }),
  mode: 'cors',
  cache: 'no-cache',
  credentials: 'include',
  redirect: 'follow',
  referrerPolicy: 'no-referrer'
})
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error('Error:', error));

第二章:响应处理

2.1 响应对象

Fetch API 的响应对象处理。

练习 2.1:响应对象示例

展示响应对象的处理方法。

响应对象示例
// 响应对象处理
fetch('https://api.example.com/data')
  .then(response => {
    // 检查响应状态
    if (!response.ok) {
      throw new Error('Network response was not ok');
    }
    // 获取响应头
    console.log(response.headers.get('Content-Type'));
    // 获取响应状态
    console.log(response.status);
    // 获取响应状态文本
    console.log(response.statusText);
    // 获取响应 URL
    console.log(response.url);
    return response.json();
  })
  .then(data => console.log(data))
  .catch(error => console.error('Error:', error));

2.2 响应数据

Fetch API 的响应数据处理。

练习 2.2:响应数据示例

展示响应数据的处理方法。

响应数据示例
// 处理不同类型的响应数据
fetch('https://api.example.com/data')
  .then(response => {
    const contentType = response.headers.get('content-type');
    if (contentType && contentType.includes('application/json')) {
      return response.json();
    } else if (contentType && contentType.includes('text/plain')) {
      return response.text();
    } else if (contentType && contentType.includes('application/octet-stream')) {
      return response.blob();
    } else {
      return response.text();
    }
  })
  .then(data => console.log(data))
  .catch(error => console.error('Error:', error));

// 处理 FormData
const formData = new FormData();
formData.append('username', 'john');
formData.append('avatar', fileInput.files[0]);

fetch('https://api.example.com/upload', {
  method: 'POST',
  body: formData
})
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error('Error:', error));

第三章:错误处理

3.1 错误类型

Fetch API 的错误处理。

练习 3.1:错误处理示例

展示错误处理的方法。

错误处理示例
// 错误处理
fetch('https://api.example.com/data')
  .then(response => {
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }
    return response.json();
  })
  .then(data => console.log(data))
  .catch(error => {
    console.error('Error:', error);
    // 处理不同类型的错误
    if (error instanceof TypeError) {
      console.log('网络错误或请求被阻止');
    } else if (error instanceof SyntaxError) {
      console.log('JSON 解析错误');
    } else {
      console.log('其他错误');
    }
  });

// 使用 async/await 处理错误
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('Error:', error);
  }
}

3.2 超时处理

Fetch API 的超时处理。

练习 3.2:超时处理示例

展示超时处理的方法。

超时处理示例
// 超时处理
function fetchWithTimeout(url, options = {}, timeout = 5000) {
  return Promise.race([
    fetch(url, options),
    new Promise((_, reject) =>
      setTimeout(() => reject(new Error('Request timeout')), timeout)
    )
  ]);
}

// 使用超时处理
fetchWithTimeout('https://api.example.com/data', {}, 5000)
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => {
    if (error.message === 'Request timeout') {
      console.log('请求超时');
    } else {
      console.error('Error:', error);
    }
  });

// 使用 AbortController 取消请求
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('请求被取消');
    } else {
      console.error('Error:', error);
    }
  });

// 取消请求
controller.abort();

第四章:高级用法

4.1 并发请求

Fetch API 的并发请求处理。

练习 4.1:并发请求示例

展示并发请求的处理方法。

并发请求示例
// 并发请求
Promise.all([
  fetch('https://api.example.com/users/1'),
  fetch('https://api.example.com/users/2'),
  fetch('https://api.example.com/users/3')
])
  .then(responses => Promise.all(responses.map(r => r.json())))
  .then(users => {
    console.log(users[0]);
    console.log(users[1]);
    console.log(users[2]);
  })
  .catch(error => console.error('Error:', error));

// 使用 async/await 处理并发请求
async function fetchUsers() {
  try {
    const [user1, user2, user3] = await Promise.all([
      fetch('https://api.example.com/users/1').then(r => r.json()),
      fetch('https://api.example.com/users/2').then(r => r.json()),
      fetch('https://api.example.com/users/3').then(r => r.json())
    ]);
    console.log(user1, user2, user3);
  } catch (error) {
    console.error('Error:', error);
  }
}

4.2 请求封装

Fetch API 的请求封装。

练习 4.2:请求封装示例

展示请求封装的最佳实践。

请求封装示例
// 请求封装
const api = {
  baseUrl: 'https://api.example.com',
  
  async request(endpoint, options = {}) {
    const url = `${this.baseUrl}${endpoint}`;
    const defaultOptions = {
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${localStorage.getItem('token')}`
      }
    };
    
    try {
      const response = await fetch(url, {
        ...defaultOptions,
        ...options,
        headers: {
          ...defaultOptions.headers,
          ...options.headers
        }
      });
      
      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
      }
      
      const contentType = response.headers.get('content-type');
      if (contentType && contentType.includes('application/json')) {
        return response.json();
      }
      return response.text();
    } catch (error) {
      console.error('Error:', error);
      throw error;
    }
  },
  
  get(endpoint, params = {}) {
    const queryString = new URLSearchParams(params).toString();
    const url = queryString ? `${endpoint}?${queryString}` : endpoint;
    return this.request(url);
  },
  
  post(endpoint, data) {
    return this.request(endpoint, {
      method: 'POST',
      body: JSON.stringify(data)
    });
  },
  
  put(endpoint, data) {
    return this.request(endpoint, {
      method: 'PUT',
      body: JSON.stringify(data)
    });
  },
  
  delete(endpoint) {
    return this.request(endpoint, {
      method: 'DELETE'
    });
  }
};

// 使用封装的 API
api.get('/users')
  .then(users => console.log(users))
  .catch(error => console.error('Error:', error));

api.post('/users', { name: 'John', age: 30 })
  .then(user => console.log(user))
  .catch(error => console.error('Error:', error));

学习建议

建议按照章节顺序学习,每完成一个练习后再进行下一个。可以通过创建实际项目来实践所学知识。