首页 > 其他分享 >fetch 在实际项目中的思考

fetch 在实际项目中的思考

时间:2024-08-18 19:55:41浏览次数:9  
标签:axios http 实际 json 思考 response fetch localhost

fetch 在实际项目中的思考

随着 fetch 的出现,可以让我们不在需要在项目中导入一些三方库来发送 http 请求。虽然浏览器中早已存在 XMLHttpRequest,但是由于它的写法比较繁琐,我们在使用的通常都是导入一些依赖库来更方便的使用它,比如 jquery 的 $.ajax()、angular 的 $http,以及最常用的 axios。但是 fetch 在实际项目中真的好用吗?

虽然我们确实可以通过 fetch 更容易的操作一些底层的操作,但是在实际项目中使用抽象的、简便的方法其实真的会比直接操作底层 API 会更省力。

错误处理

我们在学习 fetch 的基础写法会发现,它看起来非常像我们常用的依赖库的写法:

// 比如 axios 的写法

import axios from "axios";

axios
  .get("http://localhost:3000/api")
  .then((result) => console.log("success:", result))
  .catch((error) => console.log("error:", error));

通过 fetch 改写可以写成如下:

fetch("http://localhost:3000/api")
  .then((response) => response.json())
  .then((result) => console.log("success:", result))
  .catch((error) => console.log("error:", error));

看起来 fetch 只是多了一行将响应流解析成 JSON 格式的代码,看起来问题不是很大。

但是我们在认真看一下,或者实际上调用一下就会发现,它们是不一样的,前面提到的多种三方库在处理错误状态码(比如 404、500 这些)的时候都会当成是一个错误。但是 fetch 只会在网络异常(ip 解析异常、服务无法访问或者 cors)的时候才会拒绝这个 Promise,之后在 catch 中捕获。

这也就意味在上面的代码中,如果我们的响应状态码是 404,fetch 代码段还是会打印 success。如果我们想在服务端响应异常的时候返回一个拒绝状态,就需要额外添加一些代码:

fetch("http://localhost:3000/api")
  .then((response) => {
    return response.json().then((data) => {
      if (response.ok) {
        return data;
      } else {
        return Promise.reject({ status: response.status, data });
      }
    });
  })
  .then((result) => console.log("success:", result))
  .catch((error) => console.log("error:", error));

ok 的值只在响应码处于 200 - 299 的范围内才返回 true

可能很多人会觉得这没什么,即便从服务端返回的是 404 这样的状态码,也是从服务端获取的数据,说明服务端确实成功响应了。这其实是一种观点,没有什么对错之分,只不过在我看来服务端返回的错误响应还是应该认为是一种异常,但是我们没办法修改 fetch 的规范,我们只是应该存在一种更好的抽象去表示。

POST 请求

另一种常用的场景就是发送 POST 请求,当我们使用 axios 去发送,只需要简单的一行:

axios.post('http://localhost:3000/user', {
  name: 'leo'
})

但是在 fetch 中,我们却需要使用定义一堆东西,简单的设置 method、body 并不能成功请求,比如:

fetch("http://localhost:3000/user", {
  method: "POST",
  body: {
    name: "leo",
  },
})

这种简单写法发送给服务端的数据是异常的([object Object])。fetch 的 API 是非常显式的,对于发送的是 JSON 数据,我们必须把这个数据转成字符串,并添加 Content-Type: application/json 头来告诉服务端这个 payload 是 JSON,否则服务端会认为它是一个字符串。

改写如下可以正常使用:

fetch("http://localhost:3000/user", {
  method: "POST",
  headers: {
    'Content-Type': 'application/json'
  }
  body: JSON.stringify({
    name: "leo",
  }),
})

假设我们有非常多类似的请求,那就要重复写这些配置。

fetch 默认设置

如前面所说,fetch 是一种非常显式的 API,如果我们不主动设置,就不能拿到任何东西。在实际项目中,可能存在以下问题:

  1. fetch 默认是不会发送 cookie 的,如果我们的项目中依赖 cookie 来做验证就需要手动进行配置。
  2. 需要手动设置 ‘Accept: application/json’ 表明客户端可以处理 JSON 数据。
  3. fetch 默认是不支持 cors 的

所以我们在 fetch 请求中都需要设置如下:

fetch(url, {
  credentials: "include",
  mode: "cors",
  headers: {
    Accept: "application/json",
  },
});

看起来多加点配置也没什么,但是如果我们的项目中每个请求都需要添加这些呢?fetch 并没有提供可以修改默认的方法。

axios 提供了这种修改默认配置的方法,非常简便:

axios.defaults.baseURL = 'http://localhost:3000';
axios.defaults.headers.common['Accept'] = 'application/json';
axios.defaults.headers.post['Content-Type'] = 'application/json';

axios 的目标是为了能简单的调用 api 发送请求。而 fetch 的目标更远大,并不是很适合我们目前的项目。

总结

如果我们不想要导入三方库来发送请求,意味着我们就不能通过下面这一行代码实现:

function addUser(details) {
  return axios.post('http://localhost:3000/user', details);
}

而是需要封装一个这样的方法:

function addUser(details) {
  return fetch('http://localhost:3000/user', {
    mode: 'cors',
    method: 'POST',
    credentials: 'include',
    body: JSON.stringify(details),
    headers: {
      'Content-Type': 'application/json',
      'Accept': 'application/json',
    }
  }).then(response => {
    return response.json().then(data => {
      if (response.ok) {
        return data;
      } else {
        return Promise.reject({status: response.status, data});
      }
    });
  });
}

这个一看就知道在项目中是不应该存在大量这样的重复代码,我们可能需要将更多的场景考虑进来,然后进行一个封装。

那么当我们有另一个项目也需要这个封装函数的时候,是不是又要去修改、优化,来让这些 api 变得更简便、
适用。但是在这个过程中我们是不是又创建了一个发送请求的库,而不是直接使用 fetch 这个 api 呢?

当然,本文并不是在否认 fetch 是一个无用的设计,fetch 的底层设计非常好,比起 XMLHttpRequest,它能让我们对请求进行更细的控制。只不过在日常项目中这种底层 api 不是非常适用,直接使用封装好的工具可能是更好的选择。

标签:axios,http,实际,json,思考,response,fetch,localhost
From: https://blog.csdn.net/qq_42880714/article/details/141176254

相关文章

  • 一文详解帮助中心FAQ系统:定义、作用、实际应用
    在信息爆炸的时代,优质客户服务已成为企业竞争的关键要素之一。而帮助中心FAQ系统,作为客户服务体系中的重要组成部分,其重要性日益凸显。本文旨在通过清晰的结构和通俗易懂的语言,深入探讨帮助中心FAQ系统的定义及其在企业运营中的多重作用。一、定义篇:什么是帮助中心FAQ系......
  • 《心灵杀手》安装时renderer_w32_f.dll丢失:从原因分析到实际操作,全方位解决《心灵杀手
    《心灵杀手》(AlanWake)是一款备受好评的动作冒险游戏,但有时玩家在安装过程中会遇到“renderer_w32_f.dll丢失”的错误提示。这个问题通常意味着游戏启动时未能找到所需的动态链接库(DynamicLinkLibrary,DLL)文件,从而阻止了游戏的正常安装或运行。本文将探讨这一问题的常见原因......
  • 使用 prefetchComponents 进行组件预取
    title:使用prefetchComponents进行组件预取date:2024/8/17updated:2024/8/17author:cmdragonexcerpt:摘要:本文介绍Nuxt.js中的prefetchComponents功能,用于预取组件以提高用户体验。通过在客户端后台下载和缓存组件,确保在用户需要时快速加载。文章涵盖了prefetchComp......
  • 实时数仓方案五花八门,实际落地如何选型和构建!(转载)
    原文链接:https://cloud.tencent.com/developer/article/2167527【作者介绍】王磊,阿里云MVP,华院计算技术总监。著有:《图解Spark大数据快速分析实战》;《offer来了:Java面试核心知识点精讲(原理篇)》;《offer来了:Java面试核心知识点精讲(架构篇)》。编辑|韩楠约4,989字|10......
  • BeanFactoryAware 在公司中的实际应用
    引言首先要先了解BeanFactoryAware是什么?BeanFactoryAware是Spring框架中的一个接口,它的作用是让某个Bean能够获得对BeanFactory的引用。这意味着该Bean在初始化过程中可以访问Spring容器中所有的其他Bean。这在某些情况下非常有用,特别是当一个Bean需要在运......
  • Go 语言中的方法接收者自动转换机制:深入理解与实际应用
    在Go语言中,方法接收者可以是值接收者或指针接收者,而Go为开发者提供了一个方便的功能:自动接收者类型转换。这个功能使得我们在调用方法时可以更加灵活,不必担心接收者类型是否完全匹配。然而,尽管这个机制带来了便利,但开发者仍然需要注意方法接收者类型的选择,因为它们在功能、性......
  • 安装Toolkits,使用prefetch下载SRA数据库
    准备安装Toolkits建议conda安装,命令如下。(兼容性还行,没必要新建环境)condainstall-cbiocondasra-tools注意:使用时记得先激活conda环境。直接安装,请参考:SRAToolKit(sra-tools)的安装和使用配置prefetch下载路径prefetch的默认目录是配置Toolkits的路径,非常建议更......
  • Web语义化及实际应用
    你好同学,我是沐爸,欢迎点赞、收藏和关注!今天一起了解下Web语义化及其应用吧!是什么?使用合适的标签、属性,让页面能“说话“,让人和机器都能快速理解网页内容。为什么?有利于被搜索引擎搜索有利于无障碍阅读增强代码的可读性、可维护性怎么做避免使用<div>或<span>标签来......
  • Windows超高危漏洞“狂躁许可”实际利用全过程曝光!(附POC)
     自"永恒之蓝"之后,Windows再次暴露出一个影响全版本且高度稳定可利用的预认证远程代码执行(RCE)漏洞。本文将跟随漏洞披露者的第一视角,详细探讨漏洞的技术原理、利用方法,并提供相关的概念验证伪代码。文章同时附有演示视频,展示了该漏洞在最新的WindowsServer2025上的实......
  • 【架构师视角系列】风控场景下的配置中心设计思考
    声明原创文章,转载请标注。https://www.cnblogs.com/boycelee/p/18055933《码头工人的一千零一夜》是一位专注于技术干货分享的博主,追随博主的文章,你将深入了解业界最新的技术趋势,以及在Java开发和安全领域的实用经验分享。无论你是开发人员还是对逆向工程感兴趣的爱好者,都能在《......