fetch详解

119 阅读4分钟

Fetch API 是一组用于在 Web 浏览器中进行网络请求的现代 JavaScript API。它提供了一种更简洁、更强大的方式来处理网络请求,相比传统的 XMLHttpRequest 对象,Fetch API 更易于使用且功能更丰富。

特点

  1. 基于 Promise:Fetch API 是基于 Promise 的,这意味着你可以使用 Promise 的链式方法来处理异步操作,使代码更清晰易懂。
  2. 简洁的 API:Fetch API 提供了一组简洁的方法来执行各种类型的 HTTP 请求,包括 GET、POST、PUT、DELETE 等。
  3. 支持流式数据:Fetch API 支持读取和写入流式数据,这使得处理大型响应或请求时更加高效。
  4. 支持跨域请求:Fetch API 默认支持跨域请求,但在某些情况下可能需要额外配置以处理 CORS(跨域资源共享)。

基础使用

fetch() 函数发送了一个 GET 请求到指定的 URL,并返回一个 Promise 对象。使用 .then() 方法处理响应,并将其解析为 JSON 格式。如果请求失败或者响应状态码不在 200-299 范围内,将会抛出一个错误并通过 .catch() 方法捕获和处理。

fetch('https://api.example.com/data')
  .then(response => {
    if (!response.ok) {
      throw new Error('Network response was not ok');
    }
    return response.json(); // 将响应解析为 JSON 格式
  })
  .then(data => {
    // 处理返回的数据
    console.log(data);
  })
  .catch(error => {
    // 处理错误
    console.error('There was a problem with the fetch operation:', error);
  });

自定义请求头

Fetch API 允许你自定义请求头,以便在请求中包含所需的信息。你可以通过传递一个对象作为第二个参数来设置请求的配置,其中包括 headers 属性来定义请求头。

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

fetch('https://api.example.com/data', {
  method: 'POST',
  headers: headers,
  body: JSON.stringify({ username: 'example', password: '123456' })
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));

//我们创建了一个包含自定义请求头的 Headers 对象,并在请求中传递了这个对象,以便服务器能够正确解析请求。

操作标头

Response 对象还有一个Response.headers属性,指向一个 Headers 对象,对应 HTTP 回应的所有标头。

const response = await fetch(url);
for (let [key, value] of response.headers) { 
  console.log(`${key} : ${value}`);  
}

response.headers.get():根据指定的键名,返回键值。
response.headers.has(): 返回一个布尔值,表示是否包含某个标头。
response.headers.set():将指定的键名设置为新的键值,如果该键名不存在则会添加。
response.headers.append():添加标头。
response.headers.delete():删除标头。
response.headers.keys():返回一个遍历器,可以依次遍历所有键名。
response.headers.values():返回一个遍历器,可以依次遍历所有键值。
response.headers.entries():返回一个遍历器,可以依次遍历所有键值对([key, value])。
response.headers.forEach():依次遍历标头,每个标头都会执行一次参数函数。

FormData 请求数据

Fetch API 支持使用 FormData 对象来处理表单数据。你可以将 FormData 对象传递给 fetch() 函数的 body 参数,从而方便地发送表单数据。

const formData = new FormData();
formData.append('username', 'example');
formData.append('password', '123456');

fetch('https://api.example.com/login', {
  method: 'POST',
  body: formData
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));

//我们创建了一个 FormData 对象,并向其添加了表单字段。然后将该对象作为请求的 body 参数传递给 fetch() 函数。

中断请求

使用 AbortController 和 AbortSignal,可以在需要时中断 Fetch 请求。这对于需要取消或中止某些操作的情况非常有用。

const controller = new AbortController();
const signal = controller.signal;

setTimeout(() => controller.abort(), 5000); // 5秒后中断请求

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

//我们创建了一个 AbortController,并在 5 秒后调用了 abort() 方法来中断请求。

缓存

Fetch API 支持使用缓存来提高性能。你可以通过设置请求的 cache 属性来控制缓存策略。参数:default,force-cache,no-cache,no-store,only-if-cached,reload

fetch('https://api.example.com/data', {
  method: 'GET',
  cache: 'no-store' // 禁用缓存 或 'reload' 以强制重新加载资源
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));

//我们通过设置 cache 属性为 'no-store' 来禁用缓存。

读取内容

Response对象根据服务器返回的不同类型的数据,提供了不同的读取方法。

const response = await fetch(url);
response.text():得到文本字符串,用于获取文本数据,比如 HTML 文件。
response.json():得到 JSON 对象。
response.blob():得到二进制 Blob 对象,例如读取图片文件,显示在网页上。
response.formData():得到 FormData 表单对象,主要用在 Service Worker 里面,拦截用户提交的表单,修改某些数据以后,再提交给服务器。
response.arrayBuffer():得到二进制 ArrayBuffer 对象,主要用于获取流媒体文件。

fetch封装

function request(url, options = {}) {
  const defaultOptions = {
    method: 'GET',
    headers: {
      'Content-Type': 'application/json',
    },
    body: null,
  };

  const requestOptions = { ...defaultOptions, ...options };

  return fetch(url, requestOptions)
    .then(response => {
      const contentType = response.headers.get('content-type');
      if (!response.ok) {
        throw new Error(`请求失败: ${response.status}`);
      } else if (contentType && contentType.includes('application/json')) {
        return response.json();
      } else {
        return response.text();
      }
    })
    .catch(error => {
      console.error('请求失败:', error);
      throw error;
    });
}

// 使用示例
const apiUrl = 'https://jsonplaceholder.typicode.com/posts';

// 发起GET请求
request(apiUrl)
  .then(data => {
    console.log('GET请求成功:', data);
  })
  .catch(error => {
    console.error('GET请求失败:', error);
  });

// 发起POST请求
const postData = {
  title: 'foo',
  body: 'bar',
  userId: 1,
};
const postOptions = {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify(postData),
};
request(apiUrl, postOptions)
  .then(data => {
    console.log('POST请求成功:', data);
  })
  .catch(error => {
    console.error('POST请求失败:', error);
  });//将默认的请求选项定义为一个对象,并且在用户提供的选项和默认选项之间进行合并。//根据响应的内容类型来决定是解析为JSON格式还是纯文本格式。