javascript fetch(千字长文)

更新时间:

💡一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论

截止目前, 星球 内专栏累计输出 90w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 3100+ 小伙伴加入学习 ,欢迎点击围观

在现代 Web 开发中,与服务器进行数据交互是开发者最常见的任务之一。无论是获取用户信息、提交表单,还是加载动态内容,都需要通过 HTTP 请求与后端进行通信。JavaScript Fetch API 作为浏览器内置的现代解决方案,凭借其简洁的语法和强大的功能,已经成为前端开发者处理网络请求的首选工具。

本文将从零开始,通过循序渐进的方式讲解 JavaScript Fetch 的核心概念、使用场景、代码示例及最佳实践。无论你是刚接触网络请求的编程初学者,还是希望深入掌握进阶技巧的中级开发者,都能在本文中找到适合自己的知识。


一、什么是 JavaScript Fetch API?

Fetch API 是一个基于 Promise 的接口,用于发起网络请求并获取资源。它类似于传统的 XMLHttpRequest(XHR),但语法更简洁,功能更强大。

1.1 为什么选择 Fetch 而不是 XHR?

想象你是一名快递员:

  • XHR 像是骑着老式自行车送货,虽然能完成任务,但需要手动调节速度、路线,且中途无法查看包裹状态。
  • Fetch 则像驾驶一辆智能电动车,内置导航系统(Promise)和实时追踪功能(异步处理),让整个过程更高效、直观。

Fetch 的核心优势包括:

  • 基于 Promise:天然支持异步操作,代码可读性更高。
  • 灵活的请求配置:支持自定义请求头、请求方法(GET、POST 等)和请求体。
  • 跨平台兼容性:现代浏览器几乎全面支持,且可通过 polyfill 兼容旧版环境。

二、Fetch API 的基础用法

2.1 发起一个 GET 请求

最简单的 GET 请求只需一行代码:

fetch("https://api.example.com/data")  
  .then(response => response.json())  
  .then(data => console.log(data))  
  .catch(error => console.error("请求失败:", error));  

代码解析:

  1. fetch(url):发起请求,返回一个 Promise 对象。
  2. .then(response => ...):处理响应对象(response),需手动调用 json()text() 将响应体转换为可用格式。
  3. 错误处理:通过 .catch() 捕获请求过程中发生的异常。

2.2 使用 async/await 简化代码

通过 async/await,可以将异步代码写得更接近同步逻辑:

async function fetchData() {  
  try {  
    const response = await fetch("https://api.example.com/data");  
    const data = await response.json();  
    console.log(data);  
  } catch (error) {  
    console.error("请求失败:", error);  
  }  
}  

关键点:

  • async 关键字:标记函数为异步函数,允许使用 await
  • await 关键字:暂停函数执行,直到 Promise 完成或拒绝。

三、深入理解 Fetch 的核心概念

3.1 请求方法与 URL 参数

Fetch 支持多种 HTTP 方法,默认为 GET。若需发送 POST 请求,需配置 methodbody

// 发送 POST 请求  
fetch("https://api.example.com/submit", {  
  method: "POST",  
  headers: {  
    "Content-Type": "application/json"  
  },  
  body: JSON.stringify({ name: "Alice", age: 25 })  
})  
.then(response => response.json())  
.then(data => console.log("提交成功", data));  

参数详解:

  • method:指定请求类型(如 POST、PUT、DELETE)。
  • headers:定义请求头,例如设置 Content-Type 为 JSON。
  • body:请求体内容,需手动序列化为字符串(如 JSON)。

3.2 处理响应对象

Fetch 返回的 response 对象包含以下关键属性和方法:
| 属性/方法 | 说明 |
|-------------------|--------------------------------------------------------------------|
| response.ok | 布尔值,表示请求是否成功(状态码 200-299 返回 true)。 |
| response.status | 返回 HTTP 状态码(如 200、404、500)。 |
| response.json() | 将响应体解析为 JSON 对象(返回 Promise)。 |
| response.text() | 将响应体解析为字符串(适用于非 JSON 数据)。 |

实际案例:

fetch("https://api.example.com/data")  
  .then(response => {  
    if (!response.ok) {  
      throw new Error(`HTTP 错误:${response.status}`);  
    }  
    return response.json();  
  })  
  .then(data => console.log(data));  

四、错误处理与网络监控

4.1 全局错误捕获

Fetch 的 .catch() 只能捕获请求过程中发生的网络错误(如 DNS 解析失败、连接超时)。若服务器返回非 2xx 状态码,需通过 response.okresponse.status 手动判断:

fetch("https://api.example.com/invalid-endpoint")  
  .then(response => {  
    if (!response.ok) {  
      return response.json().then(error => {  
        throw new Error(`API 错误:${error.message}`);  
      });  
    }  
    return response.json();  
  })  
  .then(data => console.log(data))  
  .catch(error => console.error(error));  

4.2 设置超时机制

某些场景下,请求可能因网络延迟无限期等待。通过 setTimeout 可实现超时控制:

function fetchWithTimeout(url, options, timeout = 5000) {  
  return Promise.race([  
    fetch(url, options),  
    new Promise((_, reject) => setTimeout(() => reject(new Error("请求超时")), timeout))  
  ]);  
}  

五、进阶技巧与最佳实践

5.1 自定义请求头与身份验证

在需要身份验证的场景中,可通过 headers 添加 Authorization 头:

const token = "your-auth-token";  
fetch("https://api.example.com/protected", {  
  headers: {  
    Authorization: `Bearer ${token}`  
  }  
});  

5.2 处理文件上传

上传文件时,需使用 FormData 对象:

const formData = new FormData();  
formData.append("file", fileInput.files[0]);  
formData.append("description", "我的图片");  

fetch("/upload", {  
  method: "POST",  
  body: formData  
});  

5.3 跨域请求与 CORS

当请求的 URL 域名与当前页面不同,需确保目标服务器配置了正确的 CORS 头:

Access-Control-Allow-Origin: *  
Access-Control-Allow-Methods: GET, POST  

六、与传统 XHR 的对比

尽管 Fetch 是现代标准,但 XHR 仍存在于某些遗留系统中。以下是两者的核心差异:
| 特性 | Fetch API | XMLHttpRequest |
|--------------------|-----------------------------------|-------------------------|
| 异步机制 | Promise | 回调函数或事件监听 |
| 简单性 | 更简洁,无需手动创建对象 | 需调用 new XMLHttpRequest() |
| 响应处理 | 内置 .json() 等解析方法 | 需手动解析响应体 |


七、常见问题与解决方案

Q1: 为什么我的 POST 请求没有数据?

可能原因:未设置 Content-Type 或未正确序列化请求体。
解决方案

headers: { "Content-Type": "application/json" },  
body: JSON.stringify({ key: "value" })  

Q2: 如何在服务端配置 CORS?

在 Express 中,可通过中间件实现:

app.use((req, res, next) => {  
  res.header("Access-Control-Allow-Origin", "*");  
  res.header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");  
  next();  
});  

结论

JavaScript Fetch API 凭借其简洁的语法、强大的功能和良好的兼容性,已成为现代前端开发中不可或缺的工具。通过本文,我们系统地学习了 Fetch 的基础用法、核心概念、错误处理技巧及进阶应用场景。

无论是发送简单的 GET 请求,还是处理复杂的文件上传和身份验证,Fetch 都能提供直观且高效的解决方案。建议读者通过实际项目练习,逐步掌握其高级功能。未来,随着浏览器技术的演进,Fetch 还将带来更多惊喜,例如对流式传输(Stream)的支持,值得开发者持续关注。

希望本文能帮助你在 Web 开发的道路上更进一步!

最新发布