fetch向后端请求数据:get/post/put/patch/delete方式、解决catch不能主动捕获错误问题(超详细笔记)

news2024/11/28 14:39:19

1、什么是fetch:

  • fetch是ES6出现的,它使用了 ES6 提出的 promise 对象,为了取代XMLHttpRequest而诞生的;
  • 提到XMLHttpRequest就不得不提ajax,ajax是一种实现前后端交互的技术,而ajax是基于XMLHttpRequest模块实现的;
  • 但是因为XMLHttpRequest是一个设计粗糙的API,配置和调用方式非常混乱,而且基于事件的异步模型写起来不友好;
  • 所以使用XMLHttpRequest模块会产生回调地狱问题,因此产生了fetch,fetch是用来取代XMLHttpRequest模块的,并不是取代ajax的。
  • 不同于ajax的XMLHttpRequest方式,这个fetch代码非常的简洁,fetch也是服务于ajax技术,建立前后端连接,实现前后端数据交互的; 

2、fetch的用法:

fetch用来解决回调地狱问题;

http请求方式不同,写法也会不一样,不同的请求方式可以实现数据库的数据的增删改查;

常用的请求方式有:get()、post()、put()、patch()、delete();

get():拿到数据库里所有的数据;

post():增加数据;

put()、patch():修改数据;

delete():从数据库中删除数据;


(1)get请求方式:(默认请求方式是get方式)

格式:fetch(url).then(回调函数).then(回调函数)

<body>
    <button id="myget">get</button>
    <script>
        myget.onclick = function(){
            //get方式fetch请求
            fetch("http://localhost:3000/users").then(res=>{
                // console.log(res)
                return res.json()
            }).then(res=>{
                console.log(res) //res就是请求回来的数据
            })

        }
    </script>
</body>

用fetch的含义是:朝fetch里的地址发起请求,请求数据,最后打印,res就是请求回来的数据。
 

代码解释:

   打印第一个then里的res结果:

console.log(res) //第一个then的res
  • 第一个then,接收的res不是数据,里面没有数据;
  • 数据在res.json里,意思是把我的数据按照json格式读出来,但是直接打印res.json那拿不到数据,因为res.json也是一个promise对象,所以要return作为一个返回值在第二个then中才能拿到url里的数据。

结果: 

打印res.json:

  • 拿数据的时候,要返回这个res.json,在链式then里面接收这个数据res,res.json直接输出的结果不是数据,是一个Promise对象;
console.log(res.json())

结果: 

这个res.json也可以换成res.text,只不过res.json是转换成数组包裹的json对象,res.text是转换成json字符串格式,看下面的区别:

res.json格式:

res.text格式:

get方式传参数: 

  • get方式是从数据库中获取数据,传参数也是为了规定从数据库里读取什么样的数据;

我们先看怎么传参数:

get请求默认是把参数传在地址上,格式是:在地址后面加上“?参数”

看fetch括号里面的地址,用“?”关键字把参数写在地址后面;

代码中的参数是:“username=${username}”

<script>
        myget.onclick = function(){
            let username = "yiyi"
            fetch(`http://localhost:3000/users?username=${username}`).then(res=>{
                // console.log(res)
                return res.json()
            }).then(res=>{
                console.log(res)
            })
        }
</script>

假如没有传参数之前请求回来的完整数据是下图:(json格式数据)

{
    "users": [
      {
        "username": "yiyi",
        "password": 123,
        "id": 1
      },
      {
        "username": "linlin",
        "password": 456,
        "id": 2
      },
      {
        "username": "dd",
        "password": 789,
        "id": 3
      }
    ]
  }

这个数据也相当于数据库里的完整数据了,因为get方式是从数据库中读取数据,上面代码中get方式传的参数是“{username=yiyi}”,参照数据库那就是读取id=1的数据,读取完后的结果:

 


(2)post方式:(和get方式,就多了一个对象参数,其他都一样)

post方式:是携带传给后端的数据的,传参数是写在body里面

携带的信息可分为两种格式:表单格式和json字符串格式

post方式含义也是往数据库里新增数据;

表单格式的post请求:

fetch("http://localhost:3000/users",{
                method:'POST',
                headers:{
                    "content-type":"application/x-www-form-urlencoded"
                },
                body:"username=yiyi&password=123"
            })

get方式只需要传一个url地址就可以了,但是post是携带信息的,所以需要给fetch传第二个参数;

第二个参数是一个对象,里面放着method(请求方式)、headers(信息格式)、body(携带的信息);

表单方式和json字符串格式的headers和body不同;

headers写的是表单格式,body里的数据就要写成表单格式;headers写的是json格式,body里的数据就要写成json格式;

表单格式的header和body格式是:

header:{"content-type":"application/x-www-form-urlencoded"}

body:“键=值&键=值”

注意:body里千万不要传成对象格式,不然就解析不了了;

json格式的post请求:

  • 就把fetch里的headers和body参数换成下面这个格式就行了,其他的一样:
fetch("http://localhost:3000/users",{
                method:'POST',
                headers:{
                    "content-type":"application/json"
                },
                body:JSON.stringify({
                    username:"yiyi",
                    password:"123"
                })
            })

json字符串格式的header和body格式是:

header:{"content-type":"application/json"}

body:JSON.stringify({键:"值",键:“值”})

  • ps:为什么要加上stringify,因为括号里是对象格式,body不能接收对象格式,所以前面是加上JSON.stringify把对象格式转化为json字符串格式。


(3)put请求方式:

put方式的含义是对数据库的数据进行修改;

跟post相比较,把method和地址改了;

把method改为“PUT”;在请求地址  http://localhost:3000/users后面加上你要修改的json文件里id为几的对象,代码中加了“/1”,说明是修改id为1的对象;

fetch("http://localhost:3000/users/1",{
                method:'PUT',
                headers:{
                    "content-type":"application/json"
                },
                body:JSON.stringify({
                    username:"yiyi",
                })
            })

请求回来的json文件数据:

{
    "users": [
      {
        "username": "yiyi",
        "password": 123,
        "id": 1
      },
      {
        "username": "linlin",
        "password": 456,
        "id": 2
      },
      {
        "username": "dd",
        "password": 789,
        "id": 3
      }
    ]
  }

代码解释:代码中地址是“/1”,代表要修改id=1所在的对象信息,body里携带的是修改信息,把json文件中id=1的对象修改为: “username“:"yiyi”,修改完json文件为:

{
    "users": [
      {
        "username": "yiyi",
        "id": 1
      },
      {
        "username": "linlin",
        "password": 456,
        "id": 2
      },
      {
        "username": "dd",
        "password": 789,
        "id": 3
      }
    ]
  }

put方式是整个覆盖修改,对象里的所有值都被新来的信息覆盖。 

 


(4)patch方式:

patch方式:跟put含义一样,是修改数据库的值,把method为“PATCH”;

但是区别是:put是整个覆盖,patch是部分修改;

看代码:

fetch("http://localhost:3000/users/1",{
                method:'PATCH',
                headers:{
                    "content-type":"application/json"
                },
                body:JSON.stringify({
                    username:"haha",
                })
            })

json文件:(数据库完整数据)

{
    "users": [
      {
        "username": "yiyi",
        "password": 123,
        "id": 1
      },
      {
        "username": "linlin",
        "password": 456,
        "id": 2
      },
      {
        "username": "dd",
        "password": 789,
        "id": 3
      }
    ]
  }

修改后:只是把id=1的username改成了传过来的值“haha”,password不变

{
    "users": [
      {
        "username": "haha",
        "password": 123,
        "id": 1
      },
      {
        "username": "linlin",
        "password": 456,
        "id": 2
      },
      {
        "username": "dd",
        "password": 789,
        "id": 3
      }
    ]
  }

 

(5)delete请求方式:

  • delete是删除数据的,参数也是在地址上加“id”,选定哪一个就删除哪一个
fetch("http://localhost:3000/users/1",{
                method:'DELETE'
            })

3、fetch方法不能用catch捕获错误

虽然fetch方法能解决回调地狱问题,但是fetch不能用catch主动捕获错误,就是出错了,它不会就去走catch了,它还会继续往下执行,所以出错了需要自己去处理;

请求数据会出现问题:要么是地址填错了,填的地址没有数据;要么是地址是正确的,因为别的原因数据请求不回来,网络的问题也有可能。

那怎么找出错误是哪里出现的呢,上面我们有在控制台上打印过res这个值;

<body>
    <button id="myget">get</button>
    <script>
        myget.onclick = function(){
            fetch("http://localhost:3000/users").then(res=>{
                console.log(res)
            })
        }
    </script>
</body>

这个res值的结果是:

结果中有一个ok这个值和status状态这个值,ok这个值是当请求成功就是ture,请求失败就是false; status是请求成功为200,请求失败为404;

看ok简单一点,所以我们拿ok是true或者false来判断是否出错;

所以我们要在第一个then后面输出一下res的值,而且要进行if条件判断,

然后自己进行处理:

fetch(`http://localhost:3000/users?username=${username}`).then(res=>{
                console.log(res)
                if(res.ok){
                    return res.json()
                }else{
                    //拒绝
                    //reject后面{}放着拒绝以后要返回的值,可以自己定义,一般是返回status和
                    return Promise.reject({
                        status:res.status,
                        statusText:res.statusText
                    })
                }
                
            }).then(res=>{
                console.log(res)
            }).catch(err=>{
                console.log("error",err)
            })

如果请求不成功,也就是ok为false时,我们要主动拒绝,因为这个then默认你不写promise对象,也没有主动拒绝,它后面这个链式then就会直接调用。

我们在上面进行if判断,出错了就会走else,就会返回promise对象,里面有status当前状态,和statusText:数据是否返回成功。

测试案例:

这时候如果我们把地址填错,代码的执行是,先执行第一个then,先打印res,也就是console.log(res),然后发现ok是false,请求失败,这样就会执行拒绝的代码:return Promise.reject({})返回一个promise对象然后去执行catch里的代码,实参是promise.reject({实参})这里面大括号里面的实参,也就是:

{status:res.status,statusText:res.statusText},catch里面的err是形参,最后输出结果:

地址填错拒绝时返回的结果:

请求成功时它就会给你把数据拿回来:

完整代码:get方式:

<body>
    <button id="myget">get</button>

    <script>
        myget.onclick = function(){
            let username = "yiyi"
            fetch(`http://localhost:3000/users?username=${username}`).then(res=>{
                console.log(res)
                if(res.ok){
                    return res.json()
                }else{
                    //拒绝
                    //reject后面{}放着拒绝以后要返回的值,可以自己定义,一般是返回status和
                    return Promise.reject({
                        status:res.status,
                        statusText:res.statusText
                    })
                }
                
            }).then(res=>{
                console.log(res)
            }).catch(err=>{
                console.log("error",err)
            })
        }
    </script>
</body>

post方式:

<body>
    <button id="myget">get</button>
    <!-- <button id="mypost">post</button>
    <button id="myput">put</button>
    <button id="mypatch">patch</button>
    <button id="mydelete">delete</button> -->
    <script>
        myget.onclick = function(){
            fetch("http://localhost:3000/users",{
                method:'POST',
                headers:{
                    "content-type":"application/x-www-form-urlencoded"
                },
                body:"username=yiyi&password=123"
            })
            .then(res=>{
                console.log(res)
                if(res.ok){
                    return res.json()
                }else{
                    //拒绝
                    //reject后面{}放着拒绝以后要返回的值,可以自己定义,一般是返回status和
                    return Promise.reject({
                        status:res.status,
                        statusText:res.statusText
                    })
                }
            })
            .then(res=>{
                console.log(res)
            }).catch(err=>{
                console.log("error",err)
            })
        }
    </script>
</body>

4、fetch的缺点 

fetch最大的问题就是:存在浏览器的兼容性,

推荐一个网站:Can I use... Support tables for HTML5, CSS3, etc

这个网站能查询方法,技术在各个浏览器的兼容性问题 

红色表示不支持,黄色表示部分支持,绿色表示支持; 

不支持的浏览器,可以使用 polyfill 这个兼容性的库,把库用script标签引入,名字为:fetch.js,

polyfill库: 

 GitHub - camsong/fetch-ie8: A window.fetch JavaScript polyfill supporting IE8

找到里面的fetch.js文件: 

这个库表面上是fetch,但是里面的代码还是基于XMLHttpRequest设计的;

fetch的使用:

fetch是在promise基础上封装出来的,fetch是不用借助于任何模块任何js文件的,是内置的一个功能,直接用,不需要引入任何文件什么的。

但需要兼容浏览器的话,就把上面这个polyfill库引入进来。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/88197.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C++ Reference: Standard C++ Library reference: Containers: map: map: count

C官网参考链接&#xff1a;https://cplusplus.com/reference/map/map/count/ 公有成员函数 <map> std::map::count size_type count (const key_type& k) const;计数具有特定键的元素 在容器中搜索键值等于k的元素&#xff0c;并返回匹配的数量。 因为map容器中的所…

搞懂商业智能 BI 、数据仓库、数据中台及其关系,此文足以

数字化如火如荼&#xff0c;企业的 IT 信息化也越演越烈&#xff0c;企业管理者对数据管理也是越来越重视&#xff0c;认识到数据资产带来的价值&#xff0c;本文对这些名词术语及内涵进行系统的解析&#xff0c;便于读者对数据平台相关的概念有全面的认识。 商业智能BI 商业…

本文分享Unity中的AI算法和实现3-有限状态机FSM(下)

本文分享Unity中的AI算法和实现3-有限状态机FSM(下) 回家生孩子, 暂停了一个多月的更新, 今天重新续上, ^_^. 在上一篇文章中, 我们分享了状态机的基本理论, 然后结合Unity的Animator来熟悉了这些理论, 最后设计了我们自己的状态机并实现了框架部分. 这一篇文章, 我们将继续…

20221212 SpringCloud Alibaba

Spring Cloud Alibaba介绍主要功能组件注册中心脚手架创建实例使用RestTemplate实现微服务调用使用openfeign实现微服务调用负载均衡的使用创建多实例修改负载均衡Spring Cloud Alibaba 介绍 官方文档&#xff1a; https://spring.io/projects/spring-cloud-alibaba https://…

git stash 命令详解

1. 应用场景 2. 添加储藏 3. 查看储藏 4. 删除储藏 5. 使用储藏 6. 常见用法 1. 应用场景 git stash 命令用于将工作区中的更改和暂存区中的内容储存起来 日常开发中&#xff0c;会经常遇到这种场景 我们正在 dev 分支开发新功能&#xff0c;做到一半时&#xff0c;产品经理…

模块化、组件化和插件化

模块化&#xff1a;业务解耦、代码重用 组件化&#xff1a;模块化为基础、开发阶段每个moudle都是一个app &#xff0c;可以单独编译,并行开发 互不干扰&#xff0c;不用编译整个工程&#xff0c;打包的时候每个moudle又是moudle 不是app 只有一个app 插件化&#xff1a;也是…

【愚公系列】2022年12月 Elasticsearch数据库-ELK环境的搭建(一)

文章目录前言一、ELK环境的搭建1.前提条件2.启动Elasticsearch3.配置可视化工具 head-master3.配置kibana前言 ELK是三个开源软件的缩写&#xff0c;分别表示&#xff1a;Elasticsearch , Logstash, Kibana , 它们都是开源软件。新增了一个FileBeat&#xff0c;它是一个轻量级…

大学生可以在校搞搞副业吗?尝试做外卖跑腿项目有没有市场?

随着大学寒假的即将到来&#xff0c;40多天的假期&#xff0c;为什么大学生不利用这个机会去想明年的校园生活该如何度过&#xff0c;想要自己的校园生活过得精彩&#xff0c;就给自己找一个副业吧&#xff01; 副业&#xff01;这两个词应该是针对工作的&#xff0c;而不是针…

MapReduce 编程实例:词频统计

文章目录MapReduce 编程实例&#xff1a;词频统计一&#xff0c;准备数据文件&#xff08;1&#xff09;在虚拟机上创建文本文件&#xff08;2&#xff09;上传文件到HDFS指定目录二&#xff0c;使用IDEA创建Maven项目三&#xff0c;添加相关依赖四&#xff0c;创建日志属性文件…

【AI with ML】第 3 章 :超越基础知识:检测图像中的特征

&#x1f50e;大家好&#xff0c;我是Sonhhxg_柒&#xff0c;希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流&#x1f50e; &#x1f4dd;个人主页&#xff0d;Sonhhxg_柒的博客_CSDN博客 &#x1f4c3; &#x1f381;欢迎各位→点赞…

树上操作【点分治】 - 原理 中心分解 【POJ No. 1741】 树上两点之间的路径数 Tree

树上操作【点分治】 - 原理 中心分解 分治法指将规模较大的问题分解为规模较小的子问题&#xff0c;解决各个子问题后合并得到原问题的答案。树上的分治算法分为点分治和边分治。 点分治经常用于带权树上的路径统计&#xff0c;本质上是一种带优化的暴力算法&#xff0c;并融…

【内网安全-基础】基础知识、信息收集、工具

目录 一、基础知识 1、内网&#xff1a; 2、工作组&#xff1a; 3、域(Domain)&#xff1a; 二、基础信息收集 1、判断是否在域内 2、机器角色判断 3、出网协议判断 4、端口判断 三、常规信息收集 1、常用命令 2、常用命令 3、工具&插件 LadonGO CS插件 Adfi…

基于Java(Spring+Struts+Hibernate 框架)实现(Web)学生课程管理系统【100010038】

课程管理系统设计文档 二、引言 2.1 目的 ​ 本文档详细描述了课程管理系统的设计&#xff0c;达到引导开发的作用&#xff0c;同时实现测试人员以及用户的沟通。 ​ 本文档面向开发人员&#xff0c;测试人员以及最终用户编写&#xff0c;是了解系统的导航。 2.2 范围 ​…

Win10系统电脑连接打印机的操作方法教学

Win10系统电脑连接打印机的操作方法教学分享&#xff0c;很多用户在办公的时候都会需要使用到打印机。用用户自己购买了打印机之后&#xff0c;不懂怎么去连接自己的电脑来进行使用的方法&#xff0c;接下来我们一起来看看Win10系统电脑连接打印机的操作方法分享吧。 Win10连接…

2022职场人状态和顺风出行感受调研报告

2022年即将过去&#xff0c;作为职场人的你会如何总结&#xff1f;职场同路人又有哪些想对彼此说的话&#xff1f;近日&#xff0c;嘀嗒出行发布《2022职场人状态和顺风出行感受调研报告》&#xff0c;基于近8000名嘀嗒顺风车车主和乘客分享各自职场经历和顺风出行感受&#xf…

运维人必须掌握的 5 种常用运维监控工具

运维监控工具千千万&#xff0c;仅开源的解决方案就有流量监控&#xff08;MRTG、Cacti、SmokePing、Graphite 等&#xff09;和性能告警&#xff08;Nagios、Zabbix、Zenoss Core、Ganglia、OpenTSDB等&#xff09;可供选择。 并且每种软件都有自己的特点和功能&#xff0c;各…

WiFi热点加装短信认证怎么操作?

公共场所提供无线wifi上网服务&#xff0c;需对用户进行实名认证。手机短信实名认证以其用户体验、综合成本等优势&#xff0c;成为公共wifi上网认证的首选方案。 无线wifi上网实现信认证功能&#xff0c;需要借助上网行为管理设备搭配验证短信平台使用&#xff1b;根据无线wi…

基于Java(Jsp+Sevlet)+MySql 实现的(Web)成绩管理系统【100010041】

1 概述 1.1 开发背景 随着学生数量的日渐增多&#xff0c;学生教务系统的数据量也不断增加&#xff0c;这无疑大大增加了教务系统的负担。如果能把负责学生成绩管理的模块独立出来形成一个独立的系统&#xff0c;便可以有效降低教务系统的数据量&#xff0c;不仅可以方便管理…

阿里巴巴Java开发手册(黄山版)

阿里巴巴 Java 开发手册&#xff08;黄山版&#xff09; 链接&#xff1a;https://pan.baidu.com/s/1iKsXlq1DSbePLvuysYbA4A 提取码&#xff1a;yyds 阿里巴巴将 Java 开发手册 从 1.7.0 的嵩山版更新至 1.7.1 的黄山版&#xff0c;新增 11 条新规约&#xff0c;具体变动如下…

[ Linux ] 线程控制(线程创建,等待,终止)

在上一篇我们了解了Linux下线程的相关概念。而本篇的主要内容是线程控制。线程控制包括线程的创建&#xff0c;线程的终止&#xff0c;线程等待等问题&#xff0c;以及线程分离和Linux常见线程安全问题。 目录 1.线程控制 1.1POSIX线程库 1.2 创建线程 1.2.1 创建线程编码…