{T}

Fetch API

fetch() 是现代浏览器提供的网络请求接口,基于 Promise 设计,用于替代传统的 XMLHttpRequest。它语法简洁、链式清晰,是 Web 端与服务器通信的标准方式。

基本用法

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

使用 async/await 更直观:

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

Request 配置

第二个参数用于配置请求方法、请求头、请求体等:

js
const response = await fetch('https://api.example.com/users', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ name: 'Alice', age: 30 }),
});

常用配置项:

配置项说明示例
method请求方法GET / POST / PUT / DELETE
headers请求头对象{ 'Content-Type': 'application/json' }
body请求体JSON.stringify(data) / FormData
mode跨域模式cors / no-cors / same-origin
credentials凭证策略same-origin / include / omit
cache缓存模式default / no-store / reload
signal中断信号AbortSignal(见下文)

处理响应

fetch() 不会因 HTTP 错误状态码(如 404、500)而 reject,需要手动检查 response.ok

js
async function getData() {
  const response = await fetch('https://api.example.com/data');
  if (!response.ok) {
    throw new Error(`HTTP 错误:${response.status}`);
  }
  return await response.json();
}

响应体提供了多种解析方法:

方法返回类型适用场景
response.json()Promise<any>JSON 接口
response.text()Promise<string>纯文本、HTML
response.blob()Promise<Blob>二进制文件、图片
response.arrayBuffer()Promise<ArrayBuffer>底层二进制处理
response.formData()Promise<FormData>表单提交响应

请求中断(AbortController)

通过 AbortController 可主动取消请求,常用于组件卸载或超时控制:

js
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 5000);

try {
  const response = await fetch('https://api.example.com/data', {
    signal: controller.signal,
  });
  clearTimeout(timeoutId);
  const data = await response.json();
} catch (error) {
  if (error.name === 'AbortError') {
    console.log('请求已取消或超时');
  }
}

上传文件

结合 FormData 实现文件上传:

js
const formData = new FormData();
formData.append('avatar', fileInput.files[0]);

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

注意:使用 FormData 时不要手动设置 Content-Type,浏览器会自动添加 boundary

与 XMLHttpRequest 的对比

维度Fetch APIXMLHttpRequest
回调模型Promise 链式事件回调
流式读取支持 ReadableStream有限支持
请求中断AbortController.abort()
进度上报需结合 ReadableStream原生 onprogress
语法简洁度
提示

对于需要精细上传/下载进度条的场景,XMLHttpRequest 仍比 fetch 更直接;其余绝大多数场景推荐使用 fetch

完整可运行示例

以下 HTML 文件可直接保存为 .html 后在浏览器打开,向公开测试 API 发起 GET/POST 请求:

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>Fetch API 实战</title>
</head>
<body>
  <button id="getBtn">GET 请求</button>
  <button id="postBtn">POST 请求</button>
  <pre id="output">// 结果将显示在这里</pre>

  <script>
    const output = document.getElementById('output');

    document.getElementById('getBtn').onclick = async () => {
      try {
        const res = await fetch('https://jsonplaceholder.typicode.com/posts/1');
        if (!res.ok) throw new Error('HTTP ' + res.status);
        output.textContent = JSON.stringify(await res.json(), null, 2);
      } catch (e) {
        output.textContent = '请求失败: ' + e.message;
      }
    };

    document.getElementById('postBtn').onclick = async () => {
      try {
        const res = await fetch('https://jsonplaceholder.typicode.com/posts', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ title: 'hello', body: 'world', userId: 1 })
        });
        output.textContent = JSON.stringify(await res.json(), null, 2);
      } catch (e) {
        output.textContent = '请求失败: ' + e.message;
      }
    };
  </script>
</body>
</html>

浏览器兼容性

所有现代浏览器(Chrome、Firefox、Safari、Edge)均完整支持 fetch。生产环境如需兼容旧版浏览器(如 IE11),应引入 whatwg-fetch polyfill。