# 从入门到封装:一文搞懂 Fetch API 所有用法(新手友好)

前言

在现代前端开发中,Fetch API 已经取代了传统的 XMLHttpRequest,成为浏览器发起 HTTP 请求的标准方式。它基于 Promise 设计,语法简洁,支持 async/await,是每个前端开发者必须掌握的基础技能。

本文将从最基础的 GET 请求开始,一步步带你掌握 POST/PUT/DELETE 等进阶请求,最后教你如何封装一个通用的 Fetch 请求函数,解决原生 Fetch 的所有痛点。


一、Fetch 基础:两种核心写法

Fetch 有两种最常用的写法:.then() 链式调用和 async/await 语法糖,后者是目前项目中的主流写法。

1.1 基础 GET 请求(.then () 写法)

这是 Fetch 最原始的写法,通过 Promise 的链式调用处理异步结果:

javascript

运行

javascript 复制代码
// 发起 GET 请求获取图书列表
fetch('https://ajax-base-api-t.itheima.net/api/getbooks')
  // 第一步:获取响应对象,调用 .json() 解析 JSON 数据
  .then(res => {
    return res.json();
  })
  // 第二步:拿到解析后的业务数据
  .then(data => {
    console.log('图书列表:', data);
  })
  // 捕获网络错误(注意:404/500 不会进入这里)
  .catch(err => {
    console.error('请求失败:', err);
  });

1.2 基础 GET 请求(async/await 写法)

ES7 引入的 async/await 让异步代码看起来像同步代码,可读性大大提升:

javascript

运行

javascript 复制代码
// 用 async 标记函数为异步函数
async function getBooks() {
  // 用 await 等待 Promise 完成,直接拿到响应对象
  const response = await fetch('https://ajax-base-api-t.itheima.net/api/getbooks');
  // 等待解析 JSON 数据
  const data = await response.json();
  console.log('图书列表:', data);
}

// 调用异步函数
getBooks();

二、进阶:发送 POST/PUT/DELETE 请求

Fetch 不止能发 GET 请求,通过第二个配置对象参数,我们可以指定任意请求方法、请求头和请求体。

2.1 POST 请求(提交 JSON 数据)

最常用的场景,比如新增用户、提交表单:

javascript

运行

javascript 复制代码
async function addBook() {
  // 要提交的数据
  const bookData = {
    bookname: 'JavaScript高级程序设计',
    author: '尼古拉斯',
    publisher: '人民邮电出版社'
  };

  const response = await fetch('https://ajax-base-api-t.itheima.net/api/addbook', {
    // 指定请求方法
    method: 'POST',
    // 指定请求头:告诉服务器我发的是 JSON 格式
    headers: {
      'Content-Type': 'application/json'
    },
    // 请求体:把 JS 对象转成 JSON 字符串
    body: JSON.stringify(bookData)
  });

  const result = await response.json();
  console.log('新增结果:', result);
}

addBook();

2.2 PUT 请求(修改数据)

和 POST 几乎完全一样,只是把 method 改成 PUT

javascript

运行

php 复制代码
async function updateBook() {
  const response = await fetch('https://ajax-base-api-t.itheima.net/api/updatebook', {
    method: 'PUT',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      id: 1,
      bookname: '修改后的书名',
      author: '修改后的作者'
    })
  });

  const result = await response.json();
  console.log('修改结果:', result);
}

2.3 DELETE 请求(删除数据)

通常通过 URL 参数传递要删除的 ID:

javascript

运行

javascript 复制代码
async function deleteBook(id) {
  const response = await fetch(`https://ajax-base-api-t.itheima.net/api/delbook?id=${id}`, {
    method: 'DELETE'
  });

  const result = await response.json();
  console.log('删除结果:', result);
}

// 删除 ID 为 1 的图书
deleteBook(1);

三、为什么一定要封装 Fetch?

原生 Fetch 虽然能用,但在实际项目中会暴露出很多问题,封装是必然选择。

3.1 原生 Fetch 的 4 大痛点

  1. 重复代码太多 :每次请求都要写 methodheadersJSON.stringify()res.json(),写十次就重复十遍。
  2. 错误处理反人类 :Fetch 不会把 404/500 当成错误 ,只有网络断开时才会进入 catch,需要手动判断 res.ok
  3. 无法统一配置:接口域名、请求头、超时时间等如果分散在各个请求里,后期改一处要改几十遍。
  4. 缺少通用功能:没有内置的请求拦截、响应拦截、全局加载提示、超时取消等功能。

3.2 封装后的好处

  • 一行代码发起请求,不用写重复的配置
  • 全局统一错误处理,不用每个请求都写 try/catch
  • 统一基础配置,后期域名变更只改一处
  • 业务逻辑和网络请求分离,代码更清晰易维护

四、手把手封装一个通用 Fetch 请求函数

结合实际项目需求,我们来封装一个功能完善、新手友好的 http 函数。

4.1 最终封装代码

javascript

运行

javascript 复制代码
/**
 * 通用 Fetch 请求封装函数
 * @param {Object} options 请求配置
 * @param {string} [options.method='GET'] 请求方法
 * @param {string} options.url 请求地址
 * @param {Object} [options.params] URL 查询参数
 * @param {Object} [options.data] POST/PUT 请求体数据
 * @returns {Promise} 返回解析后的 JSON 数据
 */
async function http(options) {
  // 解构参数并设置默认值
  const { method = 'GET', url, params, data } = options;

  // 1. 处理 URL 查询参数(自动拼接到 URL 末尾)
  let fullUrl = url;
  if (params && Object.keys(params).length > 0) {
    const queryStr = new URLSearchParams(params).toString();
    fullUrl = `${fullUrl}?${queryStr}`;
  }

  // 2. 构造统一的请求配置
  const fetchOptions = {
    method: method.toUpperCase(), // 统一转大写,避免大小写问题
    headers: {
      'Content-Type': 'application/json' // 统一设置 JSON 请求头
    }
  };

  // 3. 处理 POST/PUT/PATCH 请求的请求体
  if (data && ['POST', 'PUT', 'PATCH'].includes(fetchOptions.method)) {
    fetchOptions.body = JSON.stringify(data);
  }

  // 4. 发起请求 + 统一错误处理
  try {
    const response = await fetch(fullUrl, fetchOptions);

    // 关键:手动判断 HTTP 状态码,404/500 都算失败
    if (!response.ok) {
      throw new Error(`HTTP 错误:${response.status} ${response.statusText}`);
    }

    // 解析并返回 JSON 数据
    return await response.json();
  } catch (err) {
    // 全局统一打印错误
    console.error('请求失败:', err.message);
    // 向外抛出错误,让业务层可以继续处理
    throw err;
  }
}

4.2 封装函数的使用示例

封装后,发起请求变得极其简洁:

javascript

运行

javascript 复制代码
// 1. GET 请求(带查询参数)
async function getBookById(id) {
  try {
    const result = await http({
      url: 'https://ajax-base-api-t.itheima.net/api/getbooks',
      params: { id }
    });
    console.log('查询结果:', result);
  } catch (err) {
    // 业务层可以自定义错误提示
    alert('查询图书失败:' + err.message);
  }
}

// 2. POST 请求(新增数据)
async function addNewBook() {
  try {
    const result = await http({
      method: 'POST',
      url: 'https://ajax-base-api-t.itheima.net/api/addbook',
      data: {
        bookname: '哇哈哈哈',
        author: '大大',
        publisher: '江西'
      }
    });
    console.log('新增成功:', result);
    // 新增成功后自动刷新列表
    getBookList();
  } catch (err) {
    alert('新增图书失败:' + err.message);
  }
}

// 3. GET 请求(无参数)
async function getBookList() {
  const result = await http({
    url: 'https://ajax-base-api-t.itheima.net/api/getbooks'
  });
  console.log('所有图书:', result);
}

// 调用函数
getBookById(2);
addNewBook();

五、Fetch 常见坑点总结(新手必看)

  1. await 必须和 async 成对使用 只要函数内部用了 await,函数前面必须加 async 关键字,否则会报语法错误。
  2. Fetch 不会自动拒绝 404/500 错误 这是新手最容易踩的坑,必须手动判断 res.ok,否则 404 也会被当成成功请求。
  3. URL 参数要用 URLSearchParams 处理 不要手动拼接字符串,URLSearchParams 会自动处理中文、空格、特殊字符的编码问题。
  4. 拼写错误是高频问题 常见错误:fech(少一个 t)、retrun(字母顺序颠倒)、funtion(少一个 c),VS Code 的红色波浪线会提示你。
相关推荐
东风破_1 小时前
JS 数据类型:从八种分类到栈与堆的内存真相
javascript
Slice_cy1 小时前
基于node实现服务端内核引擎
前端·后端
往事随风灬1 小时前
我被 Volta 的“智能”坑了一下午:pnpm 为何无视项目 Node 版本?
前端·vue.js
xiaofeichaichai1 小时前
Tree Shaking
前端·javascript
lichenyang4531 小时前
给 ArkTS 应用做一个内置的「Network 面板」:实时看清 SSE 每一帧和最后那张卡片
前端
倾颜1 小时前
从手写 Runner 到 LangGraph:受控 Agent 接入 LangGraph
前端·后端·langchain
UXbot2 小时前
AI网页开发工具能替代工具吗?5大平台对比
前端·人工智能·低代码·ui·原型模式·web app
wuhen_n2 小时前
从零到一!前端搭建本地轻量化 RAG 问答系统
前端·langchain·ai编程
落日漫游2 小时前
代码报错难排查?借助Gemini快速修复
前端