🎯 课程目标

完成本课程后,你将能够:

  • 理解RESTful API的基本概念和使用方法
  • 掌握fetch API进行网络请求
  • 能够处理JSON数据格式
  • 理解HTTP请求方法和状态码
  • 能够调用第三方API获取数据

📖 API概述

API(Application Programming Interface,应用程序接口)是软件系统之间通信的桥梁。在Web开发中,我们主要使用RESTful API来获取和提交数据。

✨ HTTP请求方法

  • GET:获取资源(查询)
  • POST:创建资源(新增)
  • PUT:完整更新资源(修改)
  • PATCH:部分更新资源
  • DELETE:删除资源

💻 fetch API基础

fetch是现代浏览器提供的原生API,用于发起网络请求。

发送GET请求

// 基础GET请求 fetch('https://jsonplaceholder.typicode.com/posts/1') .then(response => { // 检查响应状态 if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } return response.json(); // 解析JSON响应 }) .then(data => { console.log('数据:', data); // 输出: { userId: 1, id: 1, title: '...', body: '...' } }) .catch(error => { console.error('请求失败:', error); }); // 使用async/await async function fetchPost() { try { const response = await fetch('https://jsonplaceholder.typicode.com/posts/1'); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const data = await response.json(); console.log(data); return data; } catch (error) { console.error('请求失败:', error); } }

发送POST请求

async function createPost() { const newPost = { title: '我的新文章', body: '这是文章内容', userId: 1 }; try { const response = await fetch('https://jsonplaceholder.typicode.com/posts', { method: 'POST', // 请求方法 headers: { 'Content-Type': 'application/json' // 内容类型 }, body: JSON.stringify(newPost) // 请求体(必须序列化) }); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const data = await response.json(); console.log('创建成功:', data); // 返回包含id的新数据: { title: '我的新文章', body: '...', userId: 1, id: 101 } return data; } catch (error) { console.error('创建失败:', error); } }

发送PUT和PATCH请求

// PUT请求 - 完整更新(替换整个资源) async function updatePostPut(postId) { const updatedPost = { id: postId, title: '更新后的标题', body: '完整更新的内容', userId: 1 }; const response = await fetch(`https://jsonplaceholder.typicode.com/posts/${postId}`, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(updatedPost) }); return response.json(); } // PATCH请求 - 部分更新(只更新指定字段) async function updatePostPatch(postId) { const patchData = { title: '仅更新标题' }; const response = await fetch(`https://jsonplaceholder.typicode.com/posts/${postId}`, { method: 'PATCH', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(patchData) }); return response.json(); }

发送DELETE请求

async function deletePost(postId) { const response = await fetch(`https://jsonplaceholder.typicode.com/posts/${postId}`, { method: 'DELETE' }); if (response.ok) { console.log('删除成功'); return true; } else { console.log('删除失败'); return false; } }

📊 处理不同数据格式

// 处理JSON响应(最常用) const response = await fetch('https://api.example.com/data'); const jsonData = await response.json(); // 处理纯文本 const textResponse = await fetch('https://api.example.com/text'); const textData = await textResponse.text(); // 处理HTML const htmlResponse = await fetch('https://api.example.com/page'); const htmlData = await htmlResponse.text(); // 处理Blob(文件等二进制数据) const blobResponse = await fetch('https://api.example.com/image.jpg'); const blobData = await blobResponse.blob(); // 处理FormData(表单提交) const formData = new FormData(); formData.append('file', fileInput.files[0]); formData.append('name', '文档'); const uploadResponse = await fetch('https://api.example.com/upload', { method: 'POST', body: formData // 不需要设置Content-Type,浏览器会自动设置 }); // 处理URL编码数据 const params = new URLSearchParams(); params.append('name', '张三'); params.append('age', '25'); const formResponse = await fetch(`https://api.example.com/search?${params}`);

🔐 认证和授权

// Bearer Token认证 async function fetchWithToken() { const token = localStorage.getItem('authToken'); const response = await fetch('https://api.example.com/protected', { headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' } }); if (response.status === 401) { // Token过期,跳转登录 window.location.href = '/login'; } return response.json(); } // API Key认证 async function fetchWithApiKey() { const response = await fetch('https://api.example.com/data', { headers: { 'X-API-Key': 'your-api-key-here' } }); return response.json(); } // Basic Auth(较少使用) async function fetchWithBasicAuth() { const credentials = btoa('username:password'); // Base64编码 const response = await fetch('https://api.example.com/data', { headers: { 'Authorization': `Basic ${credentials}` } }); return response.json(); }

📡 实用API示例

以下是一些免费的REST API可用于学习和测试:

API名称用途URL
JSONPlaceholder测试APIjsonplaceholder.typicode.com
随机图片获取随机图片picsum.photos
天气API获取天气数据openweathermap.org
GitHub APIGitHub数据api.github.com
国旗API国家信息restcountries.com

实战:获取随机图片

async function fetchRandomImage() { const width = 400; const height = 300; const imageUrl = `https://picsum.photos/${width}/${height}`; const response = await fetch(imageUrl); const blob = await response.blob(); // 创建图片URL const imageUrlObj = URL.createObjectURL(blob); // 显示图片 const img = document.createElement('img'); img.src = imageUrlObj; img.style.maxWidth = '100%'; document.body.appendChild(img); return imageUrlObj; }

⚠️ 常见问题

问题原因分析解决方案
CORS错误跨域请求被阻止使用代理或后端转发请求
网络请求无响应网络问题或API不可用添加超时和重试机制
JSON解析错误响应不是有效的JSON先检查response.text()
403/401错误认证失败检查API密钥或Token
请求超时服务器响应太慢使用AbortController设置超时

✅ 课后练习

练习要求:请独立完成以下练习任务:

  1. 练习 1:调用JSONPlaceholder API,获取并显示10篇文章
  2. 练习 2:实现一个新闻应用,支持浏览、搜索新闻
  3. 选做练习:调用天气API,实现一个天气应用