fetch 的详细讲解

fetch 是一个现代化的 JavaScript API,用于发送网络请求并获取资源。它是浏览器提供的全局方法,可以替代传统的 XMLHttpRequestfetch 支持 Promise,因此更易用且代码更清晰。


1. 基本语法

1.1 语法

fetch(url, options)
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error('Error:', error));
  • 参数:

    1. url:请求的资源地址。
    2. options:可选参数,用于配置请求(如方法、头部信息、请求体等)。
  • 返回值:

  • 一个 Promise,解析为 Response 对象。

  • 1.2 示例:简单 GET 请求

    fetch('https://api.example.com/data')
      .then(response => response.json()) // 将响应解析为 JSON
      .then(data => console.log(data))   // 输出解析后的数据
      .catch(error => console.error('Error:', error)); // 捕获请求错误
    

    2. Response 对象

    Response 对象表示 fetch 请求的结果,包含以下常用属性和方法:

    1. status:HTTP 状态码。

      fetch('https://api.example.com')
        .then(response => {
          console.log(response.status); // 200, 404 等
        });
      
    2. ok:布尔值,表示请求是否成功(状态码在 200-299 之间)。

      fetch('https://api.example.com')
        .then(response => {
          if (response.ok) {
            console.log('Request was successful');
          } else {
            console.error('Request failed');
          }
        });
      
    3. json():将响应解析为 JSON。

      fetch('https://api.example.com')
        .then(response => response.json())
        .then(data => console.log(data));
      
    4. text():将响应解析为纯文本。

      fetch('https://api.example.com')
        .then(response => response.text())
        .then(data => console.log(data));
      
    5. headers:响应头部信息。

      fetch('https://api.example.com')
        .then(response => {
          console.log(response.headers.get('Content-Type'));
        });
      

    3. 配置请求

    fetch 的第二个参数 options 用于配置请求方法、头部信息、请求体等。

    3.1 常用配置

    选项 描述 示例值
    method HTTP 请求方法,默认是 GET GET, POST, PUT
    headers 请求头部信息,用于传递内容类型或认证信息 { 'Content-Type': 'application/json' }
    body 请求体,用于发送数据(POSTPUT 请求中使用) JSON.stringify({...})
    mode 请求模式,默认是 cors cors, no-cors, same-origin
    credentials 是否携带凭据,如 cookies same-origin, include
    cache 缓存模式 default, no-store, reload

    3.2 示例:POST 请求

    发送一个包含 JSON 数据的 POST 请求:

    fetch('https://api.example.com/data', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        name: 'John Doe',
        age: 30,
      }),
    })
      .then(response => response.json())
      .then(data => console.log('Success:', data))
      .catch(error => console.error('Error:', error));
    

    3.3 示例:自定义请求头

    向 API 添加身份验证令牌:

    fetch('https://api.example.com/data', {
      headers: {
        'Authorization': 'Bearer YOUR_TOKEN',
      },
    })
      .then(response => response.json())
      .then(data => console.log(data))
      .catch(error => console.error('Error:', error));
    

    4. 错误处理

    fetch 的 Promise 只有在网络错误时才会拒绝,比如断网或无法解析域名。HTTP 错误状态码(如 404 或 500)不会自动触发 catch

    4.1 检查响应状态

    需要手动检查 response.okresponse.status

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

    5. 超时和取消请求

    fetch 本身不支持超时或取消请求,可以通过 AbortController 实现。

    5.1 设置请求超时

    const controller = new AbortController();
    const timeoutId = setTimeout(() => controller.abort(), 5000); // 5 秒后中止请求
    
    fetch('https://api.example.com/data', { signal: controller.signal })
      .then(response => response.json())
      .then(data => console.log(data))
      .catch(error => {
        if (error.name === 'AbortError') {
          console.error('Fetch aborted!');
        } else {
          console.error('Error:', error);
        }
      });
    
    // 清除超时
    clearTimeout(timeoutId);
    

    6. CORS(跨域请求)

    如果请求跨域资源,服务端需要设置 Access-Control-Allow-Origin 头部。如果没有配置,浏览器会拒绝跨域请求。

    示例:配置 CORS

    服务端需要添加类似以下的头部信息:

    Access-Control-Allow-Origin: *
    Access-Control-Allow-Methods: GET, POST, PUT, DELETE
    Access-Control-Allow-Headers: Content-Type, Authorization
    

    7. 与 Axios 的对比

    fetchAxios 都是常用的网络请求工具,但有一些差异:

    特性 fetch Axios
    API 原生支持 内置于浏览器,无需安装额外库 需要安装第三方库
    Promise 支持 原生支持 原生支持
    默认错误处理 只处理网络错误,不自动处理 HTTP 错误状态 自动抛出 HTTP 错误
    自动序列化 JSON 需要手动解析响应为 JSON 自动解析 JSON 响应
    支持取消请求 使用 AbortController 实现 内置取消功能
    灵活性 标准化 API,更适合简单场景 功能丰富,适合复杂场景

    8. 高级用法

    8.1 流式响应(ReadableStream)

    fetch 可以处理流式响应(比如逐步加载大文件):

    fetch('https://api.example.com/stream')
      .then(response => response.body)
      .then(stream => {
        const reader = stream.getReader();
        const decoder = new TextDecoder('utf-8');
        reader.read().then(function processText({ done, value }) {
          if (done) {
            console.log('Stream finished');
            return;
          }
          console.log(decoder.decode(value));
          return reader.read().then(processText);
        });
      });
    

    9. 常见问题

    9.1 CORS 错误

  • 浏览器跨域请求时,服务端未正确配置 CORS
  • 解决方案:
  • 服务端设置 Access-Control-Allow-Origin
  • 使用代理服务器避免跨域。
  • 9.2 网络超时

  • fetch 默认没有超时,可以使用 AbortController 设置超时。
  • 9.3 JSON 解析错误

  • 如果 API 返回非 JSON 数据,调用 response.json() 会报错:
    fetch('https://api.example.com/data')
      .then(response => response.json())
      .catch(error => console.error('Invalid JSON:', error));
    

  • 10. 总结

    fetch 是一个强大且现代化的网络请求工具,适合大部分 Web 开发场景:

  • 优点:原生支持、Promise API、更清晰的语法。
  • 缺点:错误处理需要手动检查、默认不支持超时和取消。
  • 对于简单场景,fetch 是首选;对于更复杂的场景(如请求超时、丰富的配置需求),可以考虑使用 Axios 等第三方库。

    作者:存在后于本质

    物联沃分享整理
    物联沃-IOTWORD物联网 » javascript fetch 讲解

    发表回复