likes
comments
collection
share

你可能不需要axios,fetch()足以

作者站长头像
站长
· 阅读数 17

简介

fetch() 是一种新的 API,大大简化获取资源请求的写法。与 XMLHttpRequest 一样,Fetch 可用于发出同源请求或跨域请求。Fetch 使用的是更简洁、更强大的 API,可将请求与响应分离,并使用 promise 返回响应。 一个基本的 fetch 请求设置起来很简单, 请看下面的代码:

fetch('https://juejin.cn/post/6991413031351615519')
  .then((response) => {
      return response.json();
  })
  .then((myJson) => {
    console.log(myJson);
  });

fetch语法介绍

基础语法:

fetch(url, {options})
  • url —— 要访问的 URL。
  • options —— 可选参数:method,header 等。

options常用三个属性:

  • method:HTTP 请求的方法,POSTDELETEPUT都在这个属性设置(不设置,默认GET请求)。
  • headers:一个对象,用来定制 HTTP 请求的表头(有一些无法设置的 header,Content-LengthCookieHost等,由浏览器自动生成)。
  • body:POST 请求的数据体。

其它更多API点 => fetch

fetch 返回的 promise 对象 response 解析:

fetch('https://juejin.cn/post/6991413031351615519')
  .then((response) => console.log(response))

fetch 无法建立一个 HTTP 请求,例如网络问题,或是请求的网址不存在等,那么 promise 就会 reject。 我们可以在 response 的属性中看到 HTTP 状态:

你可能不需要axios,fetch()足以

  • status —— HTTP 状态码,例如 200。
  • ok —— 布尔值,如果 HTTP 状态码为 200-299,则为 true

我们可以利用这一点判断请求是否成功:

fetch('https://juejin.cn/post/6991413031351615519')
  .then((response) => {
    if (response.ok) {
      return response.json();
    }
    return alert(`error:${response.status}`);
  })

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

  • response.text():得到文本字符串。
  • response.json():得到 JSON 对象。
  • response.blob():得到二进制 Blob 对象。
  • response.formData():得到 FormData 表单对象。
  • response.arrayBuffer():得到二进制 ArrayBuffer 对象。

我们只能选择一种读取 body 的方法。

如果我们已经使用了 response.text() 方法来获取 response,那么如果再用 response.json(),则不会生效,因为 body 内容已经被处理过了。

封装一个fetch

export const fetch = (url, options) => {
  if (!options) options = {};
  // 默认same-origin,include不管同源请求,还是跨域请求,一律发送 Cookie。
  // if (!options.credentials) options.credentials = 'include'; 
  if (options.body && typeof options.body === 'object') options.body = JSON.stringify(options.body); // 转化JSON 字符串
  if (options.body && !options.method) options.method = 'POST'; // 存在body,默认请求方法POST
  if (options.method) options.method = options.method.toUpperCase(); // 兼容下,字符串转换为大写
  // 提交JSON数据时,如果没传将默认值'text/plain;charset=UTF-8'改为'Content-Type': 'application/json'
  if (['POST', 'PUT', 'DELETE'].includes(options.method || '')) {
    options.headers = Object.assign(
      {},
      options.headers || {
        'Content-Type': 'application/json',
      },
    );
  }

  const checkStatus = res => {
    // 根据status做不同的处理
    if (res.status === 401) {
      window.location.href = '/login';
    }

    if (res.status === 405 || res.status === 403) {
      window.location.href = '/403';
    }

    if (res.status === 404) {
      notification.error({ message: '接口不存在' });
    }

    return res;
  };

  const filter = res => {
    if (res.code !== 0) {
      notification.error({
        message: '错误',
        description: res.message || '网络错误,请重试!',
      });
      throw res;
    }
    res.data = res;
    return res.data; // 返回数据
  };

  return (
    window
      // 建立连接
      .fetch(url, options)
      // 检验响应码
      .then(res => checkStatus(res))
      // 格式转换,这里我就默认json
      .then(res => res.json())
      // 根据业务需求,进行对应过滤
      .then(res => filter(res))
      .catch(err => console.log(`请求失败! + url: ${url}`, err))
  );
};

参考链接

转载自:https://juejin.cn/post/7234795667478413370
评论
请登录