首页
/ MDN项目详解:现代Web请求利器Fetch API使用指南

MDN项目详解:现代Web请求利器Fetch API使用指南

2025-07-07 00:48:11作者:袁立春Spencer

什么是Fetch API

Fetch API是现代浏览器提供的用于发起网络请求的JavaScript接口,它取代了传统的XMLHttpRequest(XHR),采用基于Promise的设计模式,完美契合现代Web开发需求。与XHR相比,Fetch API具有以下优势:

  1. 基于Promise的异步处理机制,避免了回调地狱
  2. 天然支持CORS(跨域资源共享)
  3. 与Service Worker无缝集成
  4. 提供更简洁直观的API设计

基础用法示例

让我们从一个最简单的Fetch示例开始:

async function fetchData() {
  const url = "https://api.example.com/data";
  
  try {
    const response = await fetch(url);
    
    if (!response.ok) {
      throw new Error(`HTTP错误! 状态码: ${response.status}`);
    }
    
    const data = await response.json();
    console.log(data);
  } catch (error) {
    console.error("请求失败:", error);
  }
}

这个示例展示了Fetch API的基本工作流程:

  1. 调用fetch()发起请求
  2. 检查响应状态
  3. 解析响应体为JSON格式
  4. 处理可能的错误

配置请求参数

Fetch API提供了丰富的配置选项,让我们可以定制各种类型的HTTP请求。

请求方法设置

默认情况下,fetch使用GET方法,但我们可以通过method选项指定其他HTTP方法:

const response = await fetch("https://api.example.com/resource", {
  method: "POST", // 可以是GET、POST、PUT、DELETE等
});

请求头设置

我们可以通过headers选项设置自定义请求头:

const response = await fetch(url, {
  headers: {
    "Content-Type": "application/json",
    "Authorization": "Bearer token123"
  }
});

或者使用Headers对象:

const headers = new Headers();
headers.append("Content-Type", "application/json");

const response = await fetch(url, { headers });

请求体设置

对于POST、PUT等需要发送数据的请求,我们可以通过body选项设置请求体:

const response = await fetch(url, {
  method: "POST",
  body: JSON.stringify({ key: "value" }),
  headers: { "Content-Type": "application/json" }
});

支持多种数据类型作为请求体:

  • 字符串
  • FormData对象(适合文件上传)
  • Blob/BufferSource
  • URLSearchParams(适合表单编码数据)
  • ReadableStream

处理响应

检查响应状态

Fetch API不会因为HTTP错误状态码(如404或500)而拒绝Promise,我们需要手动检查:

if (!response.ok) {
  throw new Error(`请求失败,状态码: ${response.status}`);
}

解析响应体

Response对象提供了多种方法来解析响应体:

const text = await response.text();  // 解析为文本
const json = await response.json(); // 解析为JSON
const blob = await response.blob(); // 解析为Blob对象
const formData = await response.formData(); // 解析为FormData

处理响应头

我们可以通过headers属性访问响应头:

const contentType = response.headers.get("content-type");
const allHeaders = Object.fromEntries(response.headers.entries());

高级特性

跨域请求处理

Fetch API默认使用CORS机制处理跨域请求:

// 允许跨域请求(默认)
const response = await fetch("https://other-domain.com/data");

// 禁止跨域请求
const response = await fetch("https://other-domain.com/data", {
  mode: "same-origin"
});

// 简单跨域请求(受限)
const response = await fetch("https://other-domain.com/data", {
  mode: "no-cors"
});

凭据控制

控制是否发送cookie等凭据:

// 不发送凭据(默认)
const response = await fetch(url, { credentials: "omit" });

// 同源请求发送凭据
const response = await fetch(url, { credentials: "same-origin" });

// 总是发送凭据(跨域时需服务器配合)
const response = await fetch(url, { credentials: "include" });

请求取消

通过AbortController实现请求取消:

const controller = new AbortController();

// 设置超时自动取消
const timeoutId = setTimeout(() => controller.abort(), 5000);

try {
  const response = await fetch(url, {
    signal: controller.signal
  });
  clearTimeout(timeoutId);
  // 处理响应
} catch (error) {
  if (error.name === "AbortError") {
    console.log("请求被取消");
  } else {
    console.error("请求失败:", error);
  }
}

最佳实践

  1. 错误处理:始终处理可能的错误,包括网络错误和HTTP错误状态
  2. 超时控制:结合AbortController实现请求超时
  3. 请求重用:对于需要多次使用的请求,使用Request对象
  4. 响应类型检查:在解析响应体前检查Content-Type
  5. 性能优化:对于大文件下载,使用流式处理

常见问题解答

Q: Fetch和XHR有什么区别? A: Fetch基于Promise设计,API更简洁,天然支持流式数据处理,但XHR支持进度事件而Fetch不支持。

Q: 为什么404响应不会触发catch? A: Fetch只在网络故障时拒绝Promise,HTTP错误状态需要通过response.ok或response.status检查。

Q: 如何上传文件? A: 使用FormData对象:

const formData = new FormData();
formData.append("file", fileInput.files[0]);

const response = await fetch("/upload", {
  method: "POST",
  body: formData
});

Q: 如何发送URL编码的表单数据? A: 使用URLSearchParams:

const params = new URLSearchParams();
params.append("key1", "value1");
params.append("key2", "value2");

const response = await fetch("/submit", {
  method: "POST",
  body: params,
  headers: { "Content-Type": "application/x-www-form-urlencoded" }
});

通过本文,您应该已经掌握了Fetch API的核心用法和最佳实践。Fetch API作为现代Web开发的标配,合理使用可以大大简化网络请求相关的代码,提升应用性能和开发效率。