登录
首页 >  文章 >  前端

JavaScriptfetchAPI简介与使用方法

时间:2025-07-30 19:45:30 111浏览 收藏

JavaScript Fetch API 是现代 Web 开发中发起网络请求的利器。它以 Promise 为基础,简化了异步操作,替代了传统的 XMLHttpRequest。Fetch API 支持 GET、POST 等多种 HTTP 方法,并提供更直观的错误处理机制,区分网络错误与 HTTP 错误。通过 AbortController,开发者可以轻松实现请求取消或超时控制。此外,Fetch API 还具备丰富的配置选项,如自定义 Headers、跨域模式、凭证控制、缓存策略等,赋予开发者强大的灵活性和控制能力。本文将深入探讨 Fetch API 的基本用法、与 XMLHttpRequest 的区别、错误处理方法,以及高级用法和配置选项,助你掌握这一核心 Web 开发技术。

fetch API 是现代 Web 开发中用于发起网络请求的核心工具。1. 它基于 Promise,简化了异步操作,替代了传统的 XMLHttpRequest;2. 支持多种 HTTP 方法如 GET、POST 及文件上传等;3. 提供更直观的错误处理机制,区分网络错误与 HTTP 错误;4. 通过 AbortController 实现请求取消或超时控制;5. 拥有丰富的配置选项,如自定义 Headers、跨域模式、凭证控制、缓存策略等,使其具备强大的灵活性和控制能力。

JavaScript的fetch API是什么?如何发起网络请求?

JavaScript 的 fetch API 是现代 Web 开发中用于发起网络请求的核心工具。它提供了一种更强大、更灵活的方式来替代传统的 XMLHttpRequest,通过基于 Promise 的接口,让异步操作的管理变得直观许多,大大简化了数据获取的流程。你可以用它来发送各种类型的 HTTP 请求,比如获取数据、提交表单、上传文件等等。

JavaScript的fetch API是什么?如何发起网络请求?

解决方案

发起一个网络请求,最基本的就是使用 fetch() 函数。它至少需要一个参数,那就是你想要请求的资源路径。

// 发起一个GET请求
fetch('https://api.example.com/data')
  .then(response => {
    // 检查响应是否成功 (HTTP状态码在200-299之间)
    if (!response.ok) {
      // 如果不是,抛出一个错误,让后续的.catch捕获
      throw new Error(`HTTP error! status: ${response.status}`);
    }
    // 解析JSON格式的响应体
    return response.json();
  })
  .then(data => {
    // 处理获取到的数据
    console.log('数据已获取:', data);
  })
  .catch(error => {
    // 捕获任何网络错误或上面抛出的HTTP错误
    console.error('获取数据时发生错误:', error);
  });

// 发起一个POST请求并发送JSON数据
const postData = {
  name: '张三',
  age: 30
};

fetch('https://api.example.com/users', {
  method: 'POST', // 指定请求方法
  headers: {
    'Content-Type': 'application/json' // 告诉服务器我们发送的是JSON
  },
  body: JSON.stringify(postData) // 将JavaScript对象转换为JSON字符串
})
  .then(response => {
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }
    return response.json(); // 或者 response.text() 如果预期是文本
  })
  .then(data => {
    console.log('用户创建成功:', data);
  })
  .catch(error => {
    console.error('创建用户时发生错误:', error);
  });

fetchXMLHttpRequest有什么不同?为什么我应该选择fetch

说实话,我刚接触 fetch 的时候,第一感觉就是“这玩意儿比 XMLHttpRequest (XHR) 简洁太多了”。以前用 XHR,你需要手动监听各种事件(onloadonerroronprogress),处理状态码,而且回调嵌套多了,代码就变得特别难以维护,就是所谓的“回调地狱”。那种感觉,就像你在一个迷宫里找出口,每一步都得小心翼翼地挂上钩子,生怕哪个环节断了。

JavaScript的fetch API是什么?如何发起网络请求?

fetch 彻底改变了这一切。它基于 Promise,这意味着你可以使用 .then().catch() 来链式处理异步操作,代码读起来就像同步代码一样,逻辑清晰得多。一个 fetch 请求会返回一个 Promise,这个 Promise 解析为一个 Response 对象。这个 Response 对象非常强大,它包含了响应的所有信息,比如 status (HTTP状态码)、ok (一个布尔值,表示状态码是否在 200-299 之间)、headers 等等。最方便的是,它提供了 json()text()blob() 等方法来异步解析响应体,这些方法本身也返回 Promise,进一步简化了数据处理。

我个人觉得,选择 fetch 的理由主要有几点:

JavaScript的fetch API是什么?如何发起网络请求?
  1. 现代化和简洁:代码量明显减少,可读性大幅提升。
  2. Promise 原生支持:与 async/await 语法结合,异步代码写起来几乎和同步代码一样顺滑,大大提升开发效率和代码可维护性。
  3. 更强大的 APIRequestResponse 对象提供了更细致的控制和信息访问能力。例如,你可以轻松地检查响应头、处理不同类型的数据流。
  4. 流式处理能力fetch 可以处理响应流,这对于处理大文件下载或实时数据流非常有用,虽然日常开发中可能不常用,但关键时刻能派上大用场。

所以,除非你需要支持一些非常老的浏览器(fetch 在 IE 浏览器上需要 Polyfill),否则 fetch 几乎是现代 Web 开发中发起网络请求的首选。它让网络请求这个曾经的痛点,变得没那么让人头疼了。

如何处理fetch请求中的错误和异常?

处理 fetch 请求中的错误,说起来有点意思,因为它不像 XMLHttpRequest 那样,只要 HTTP 状态码不是 2xx 就直接进 onerrorfetch 的 Promise 在遇到网络错误(比如断网、DNS解析失败)时才会 reject。但如果服务器返回了 4xx 或 5xx 这样的 HTTP 错误状态码,fetch 的 Promise 依然会成功解析resolve),只不过 Response 对象的 ok 属性会是 false。这刚开始可能会让人有点困惑,因为你可能会期待所有非成功的响应都直接进 .catch()

所以,正确的错误处理姿势通常是这样的:

  1. 网络错误:使用 .catch() 捕获。这是处理真正网络中断、请求无法发送或接收的情况。

    fetch('/api/nonexistent-endpoint') // 假设这个端点不存在,会是网络错误或跨域问题
      .then(response => response.json())
      .catch(error => {
        console.error('网络请求失败:', error); // 比如 TypeError: Failed to fetch
      });
  2. HTTP 错误(4xx, 5xx):在 .then() 链中检查 response.ok 属性。如果 response.okfalse,你就应该手动抛出一个错误。

    fetch('/api/unauthorized') // 假设返回401 Unauthorized
      .then(response => {
        if (!response.ok) {
          // 抛出带有状态码和文本的错误
          return response.text().then(text => {
            throw new Error(`HTTP 错误! 状态: ${response.status}, 消息: ${text}`);
          });
        }
        return response.json();
      })
      .then(data => console.log('数据:', data))
      .catch(error => {
        console.error('处理请求时发生错误:', error); // 捕获到我们自己抛出的错误
      });

    这里 response.text() 也是一个 Promise,所以需要再 .then() 一次来获取错误消息。这确实是 fetch 在错误处理上稍微有点“绕”的地方,需要多写一行。

  3. 请求超时或取消fetch 本身没有内置超时机制,但你可以通过 AbortController 来实现。这对于用户长时间等待或者页面跳转时取消未完成的请求非常有用。

    const controller = new AbortController();
    const signal = controller.signal;
    
    // 设置一个超时定时器
    const timeoutId = setTimeout(() => controller.abort(), 5000); // 5秒后取消请求
    
    fetch('/api/long-running-task', { signal })
      .then(response => {
        clearTimeout(timeoutId); // 请求成功,清除定时器
        if (!response.ok) {
          throw new Error(`HTTP 错误! 状态: ${response.status}`);
        }
        return response.json();
      })
      .then(data => console.log('任务完成:', data))
      .catch(error => {
        clearTimeout(timeoutId); // 捕获到错误,也清除定时器
        if (error.name === 'AbortError') {
          console.warn('请求被取消或超时:', error.message);
        } else {
          console.error('请求失败:', error);
        }
      });
    
    // 可以在需要时手动取消
    // controller.abort();

    AbortController 抛出的错误 nameAbortError,你可以根据这个来区分是超时/取消还是其他类型的错误。这种细致的错误处理,能让你的应用在面对各种网络状况时更加健壮。

fetch API有哪些高级用法和配置选项?

fetch 的强大之处远不止于简单的 GET 和 POST。它的第二个参数是一个 options 对象,里面包含了大量可配置的选项,让你能精细控制请求的方方面面。我这里挑几个我个人觉得特别有用或容易被忽视的:

  1. 自定义请求头 (Headers):这是最常用的一个。你可以通过 headers 选项来添加自定义的 HTTP 头,比如认证 token、内容类型等。

    fetch('/api/protected-data', {
      headers: {
        'Authorization': 'Bearer your_jwt_token',
        'X-Custom-Header': 'HelloFetch'
      }
    });

    你也可以创建一个 Headers 对象来更结构化地管理请求头:

    const myHeaders = new Headers();
    myHeaders.append('Content-Type', 'application/json');
    myHeaders.append('Accept', 'application/json');
    
    fetch('/api/users', {
      method: 'POST',
      headers: myHeaders,
      body: JSON.stringify({ name: 'Alice' })
    });
  2. 跨域请求模式 (mode):这个选项决定了请求的跨域行为。

    • cors (默认):允许跨域请求,但受 CORS 策略限制。
    • no-cors:用于向其他源发出请求,但响应会被浏览器限制,你无法访问响应头或状态码,只能用于发送请求。这主要是为了兼容一些遗留系统,不推荐在常规场景使用。
    • same-origin:只允许同源请求。
      fetch('https://another-domain.com/data', { mode: 'cors' });
  3. 凭证模式 (credentials):控制是否随请求发送 cookies、HTTP 认证信息等凭证。

    • omit (默认):不发送任何凭证。
    • same-origin:只在同源请求时发送凭证。
    • include:无论是否跨域,都发送凭证。如果你需要跨域携带 cookies,就必须设置这个。
      fetch('https://api.example.com/profile', { credentials: 'include' });
  4. 缓存控制 (cache):决定请求如何与 HTTP 缓存交互。

    • default:遵循浏览器默认的缓存行为。
    • no-store:不使用缓存,也不将响应存储到缓存。
    • reload:强制从网络获取新资源,不使用缓存,但会将新响应存储到缓存。
    • no-cache:在发送请求前,会先验证缓存副本是否过期。
    • force-cache:强制使用缓存,即使过期也用,除非没有缓存。
    • only-if-cached:只在缓存中有副本时才使用,否则失败。
      fetch('/api/data', { cache: 'no-cache' });
  5. 发送文件 (FormData):对于文件上传或发送复杂的表单数据,FormData 对象是你的好帮手。

    const formData = new FormData();
    formData.append('username', 'JohnDoe');
    formData.append('profilePic', myFileInput.files[0]); // myFileInput 是 <input type="file"> 元素
    
    fetch('/upload', {
      method: 'POST',
      body: formData // fetch 会自动设置 Content-Type 为 multipart/form-data
    });

    这里 fetch 会自动处理 Content-Type 头,你不需要手动设置 multipart/form-data

这些高级选项让 fetch 不仅仅是一个简单的 HTTP 客户端,它能够处理各种复杂的网络场景,让开发者对请求的生命周期和行为有更强的掌控力。虽然刚开始学可能觉得选项有点多,但一旦掌握了,你会发现它们都是解决特定问题的利器。

到这里,我们也就讲完了《JavaScriptfetchAPI简介与使用方法》的内容了。个人认为,基础知识的学习和巩固,是为了更好的将其运用到项目中,欢迎关注golang学习网公众号,带你了解更多关于的知识点!

相关阅读
更多>
最新阅读
更多>
课程推荐
更多>