后端程序员入门react笔记(六)- 讲透Promise与Fetch

js声明变量的三种方式

我们通常使用 var let 和const来声明js的变量,但是这三者有什么区别呢?

  • var的变量可以是全局的或者函数作用域,而let和const只能是块级作用域
  • var和let可以重新赋值,而const是不允许重新赋值的,
  • var可以在一个作用域内重新声明,let和const只能声明一次
  • 一般来说,建议使用 let 和 const 来声明变量,因为它们提供了更严格的作用域控制和可变性。var 仍然可以在某些情况下使用,例如在需要全局作用域的变量时。

js的异步编程

用过ajax请求的人应该都知道有这么一个参数async,即是否异步,如果是异步,则设置为true,如果是非异步,则为false,我们举例看一下

<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script>console.log(1);$.ajax({url: "./a.json",type: "post",dataType: "text",async: true,//异步data: {},success: function(data){console.log(2);}});console.log(3);
</script>
  • 结果返回的是1 3 2 ,即js并没有等待ajax的结果,而是继续往下执行代码,Ajax的返回结果是通过success回调函数调用的。如果把async设置为false,则结果是1 2 3
    在这里插入图片描述

回调地狱

那么这个时候来了一个需求,要求根据第一个Ajax的请求结果作为条件来发起第二个Ajax请求,然后以第二个Ajax的请求结果作为条件发送第三个Ajax请求,那么形式可能就是这样的

<script>$.ajax({url: "./a.json",type: "post",dataType: "text",async: true,success: function(data){$.ajax({url: "./a.json",type: "post",dataType: "text",async: true,success: function(data){$.ajax({url: "./a.json",type: "post",dataType: "text",async: true,success: function(data){}})}})}})
</script>

一层层的嵌套,这就是回调地狱。这即不好看,也不好写,逻辑更是混乱。那么怎么办呢?至少作为后端,我们取使用orm取数据的时候都会用到一种链式操作,比如Model(user).Where("email = ?",query.Email).Where("password = ?",utils.Md5Encode(query.PassWord)).First(user)。我们永远可以在之前的操作结果上加条件。那么js有没有这种写法呢?有的,这个东西就叫做promise

promise

Promise是ES6新增的一个类,可以翻译为承诺(许诺、契约等),promise允许你将异步操作链接在一起,并以同步的方式处理它们的结果。
既然是一个类,就会有构造函数,promise的构造函数叫executor,我们可以这样创建一个promise

const myPromise = new Promise((resolve, reject) => {// 这里是一些异步操作if (success) {resolve(result);} else {reject(error);}
});

处理promise

有两种处理promise的方法

  • .then():当 Promise 成功完成时调用。它接受一个回调函数,该函数将接收 Promise 的结果作为参数。
  • .catch():当 Promise 失败时调用。它接受一个回调函数,该函数将接收 Promise 的错误作为参数。注意,如果.then里面处理的err则catch无法再次捕捉
    注意,.then() 和 .catch() 回调总是返回一个新的 Promise,这使得可以链接 Promise。
var promise = new Promise(function(resolve, reject) {if (/* 异步操作成功 */){resolve(value);} else {reject(error);}
});
promise.then(function(value) {// 如果调用了resolve方法,执行此函数
}, function(value) {// 如果调用了reject方法,执行此函数
});

演示

<script>var getJSON = function (url) {//创建一个promise并返回return new Promise(function (resolve, reject) {//进行一些异步操作const client = new XMLHttpRequest();client.open("GET", url);client.onreadystatechange = handler;client.responseType = "json";client.setRequestHeader("Accept", "application/json");client.send();function handler() {if (this.readyState === 4) {if (this.status === 200) {//如果成功则执行resolveresolve(this.response);} else {//如果失败则执行resolvereject(new Error(this.statusText));}}};});};getJSON("./a.json").then(function(json) {console.log(json);}, function(error) {console.error('出错了', error);});
</script>

链式调用

Promise 可以链接在一起,形成一个链式调用:

myPromise1.then((result1) => {return myPromise2(result1);}).then((result2) => {// 处理最终结果}).catch((error) => {// 处理错误});

promise的状态

promise实例的状态有三种

  • pending: 初始状态,未执行
  • fulfilled: 操作完成
  • rejected: 操作失败

调用流程图

在这里插入图片描述

一道面试题

下面这道题目,输出结果是多少?

    console.log(1);new Promise(function (resolve, reject){console.log(2);reject(true);console.log(3);window.setTimeout(function (){console.log(4);resolve(false);}, 0);}).then(function(){console.log(5);}, function(){console.log(6);});console.log(7);
  • 接下来我们解析一下上面的代码,console.log(1)执行输出1,构造promise对象要先执行executor,输出console.log(2);异步调用reject(true);继续输出console.log(3);setTimeout也是异步调用,被放到事件队列。promise对象创建完毕,继续console.log(7);reject事件发起回调,执行console.log(6);setTimeout发起回调,执行 console.log(4);,由于reject之后 promise的状态无法再次被修改,resolve(false)不会改变状态,所以不执行,最终执行结果就是 1 2 3 7 6 4

fetch

如果你了解xhr,那么你就很容易明白fetch,因为fetch就是js原生支持的,xhr的替代方案。Fetch被称为下一代 Ajax 技术,采用 Promise 的方式来处理数据。它是一种简洁明了的API,比 XMLHttpRequest 更加简单易用。

fetch的初试

我们来简单实现一个fetch的demo,我们前面说了,是js原生的api,无需引入其他包

    let url="./a.json"fetch(url).then((res)=>{console.log(res);}).catch((err)=>{console.log(err);})
  • 我们查看输出,请求的返回值是一个json,但是这个fetch返回的response没有我们的数据啊,为什么?这我们就要说到了关注分离原则
    在这里插入图片描述

关注分离

关注分离是一种软件设计原则,旨在将不同的功能模块分离开来,使其各自专注于特定的任务。在 Web 开发中,这意味着将输入、输出和状态跟踪等不同方面的功能分离开来,以便更好地组织代码并提高可维护性。
比如咱们上面举例的这个fetch,response并不是说我获取到了数据,重点在于我链接服务成功了,服务器给我响应了,不管是404还是500还是200,只要服务器响应我了,我就认为我任务完成了。
在这里插入图片描述
那么我们怎么获取数据呢?那我们就要在这个基础上,继续获取promise里面的内容

    let url="./a.json"fetch(url).then((res)=>{console.log(res);//把结果作为promise返回return  res.json()}).then((json)=>{//处理上一个返回的promiseconsole.log(json);}).catch((err)=>{console.log(err);})

一个完整的fetch请求

一个完整的fetch,在url后面,其实还可以跟一个config对象,config对象属性如下,可以配置请求方式,data,headers等信息

{/** A BodyInit object or null to set request's body. */body?: BodyInit | null;/** A string indicating how the request will interact with the browser's cache to set request's cache. */cache?: RequestCache;/** A string indicating whether credentials will be sent with the request always, never, or only when sent to a same-origin URL. Sets request's credentials. */credentials?: RequestCredentials;/** A Headers object, an object literal, or an array of two-item arrays to set request's headers. */headers?: HeadersInit;/** A cryptographic hash of the resource to be fetched by request. Sets request's integrity. */integrity?: string;/** A boolean to set request's keepalive. */keepalive?: boolean;/** A string to set request's method. */method?: string;/** A string to indicate whether the request will use CORS, or will be restricted to same-origin URLs. Sets request's mode. */mode?: RequestMode;/** A string indicating whether request follows redirects, results in an error upon encountering a redirect, or returns the redirect (in an opaque fashion). Sets request's redirect. */redirect?: RequestRedirect;/** A string whose value is a same-origin URL, "about:client", or the empty string, to set request's referrer. */referrer?: string;/** A referrer policy to set request's referrerPolicy. */referrerPolicy?: ReferrerPolicy;/** An AbortSignal to set request's signal. */signal?: AbortSignal | null;/** Can only be null. Used to disassociate request from any Window. */window?: null;
}

async 和await

上面例子中,我们通过.then返回的promise再次.then ,这明显是有些繁琐的。那么怎么办?我们这里就可以用到async 和await,

    let url = "./a.json"async function getJson() {try {let res = await fetch(url);if (res.status !== 200) {throw new Error("请求失败")}const json = await res.json();console.log(json);} catch (e) {console.log(e);}}getJson()

那么这里面的async和await是什么意思呢?

  • async 关键字提供了一种更简单的方法来处理基于异步 Promise 的代码。在一个函数的开头添加 async,就可以使其成为一个异步函数。注意,async 函数总是返回一个 Promise 对象。
  • 在异步函数中,我们可以在调用一个返回 Promise 的函数之前使用 await 关键字。这使得代码在该点上等待,直到 Promise 被完成,这时 Promise 的响应被当作返回值,或者被拒绝的响应被作为错误抛出。这样我们就能够编写像同步代码一样的异步函数,注意,只能在 async 函数内使用 await 关键字,用于等待 Promise 对象 resolved 后返回结果。
  • await 会暂停 async 函数的执行,等待 Promise 返回结果,然后恢复函数执行并返回数据。
  • await 表达式如果抛出错误,会被捕获并返回 Promise 对象的 reject 状态。

promise的并行调用和链式调用示例

<script>let url1 = "./a1.json"let url2 = "./a2.json"let url3 = "./a3.json"async function getJson1(n) {console.log(n);try {let res = await fetch(url1);if (res.status !== 200) {throw new Error("请求失败")}return res.json();} catch (e) {console.log(e);}}async function getJson2(n) {console.log(n);try {let res = await fetch(url2);if (res.status !== 200) {throw new Error("请求失败")}return res.json();} catch (e) {console.log(e);}}async function getJson3(n) {console.log(n);try {let res = await fetch(url3);if (res.status !== 200) {throw new Error("请求失败")}return res.json();} catch (e) {console.log(e);}}//并行执行多个异步操作async function getAll(){//等待所有执行完毕let res= await Promise.all([getJson1(1), getJson2(2), getJson3(3)])let total=res[0].age+res[1].age+res[2].ageconsole.log(total);return total;}getAll()//链式调用 根据前面的结果调用下一个async function chain(){let init=0let res1=await getJson1(init);let res2=await getJson2(res1.age);let res3=await getJson3(res2.age);console.log(res3.age);}chain()</script>

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

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

相关文章

Linux课程四课---Linux开发环境的使用(vim编辑器的相关)

作者前言 &#x1f382; ✨✨✨✨✨✨&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f382; ​&#x1f382; 作者介绍&#xff1a; &#x1f382;&#x1f382; &#x1f382; &#x1f389;&#x1f389;&#x1f389…

常见漏洞的流量特征

1、SQL注入漏洞 查看url / Referer字段/User-Agent字段/cookie字段 出现一些特殊字符&#xff08;eg&#xff1a;单引号【‘】、双引号【“”】、括号【&#xff08;&#xff09;】、单引号括号【‘&#xff08;】、双引号括号【“&#xff08;】等一些常见的特殊的字符&#…

改进的yolo交通标志tt100k数据集目标检测(代码+原理+毕设可用)

YOLO TT100K: 基于YOLO训练的交通标志检测模型 在原始代码基础上&#xff1a; 修改数据加载类&#xff0c;支持CoCo格式&#xff08;使用cocoapi&#xff09;&#xff1b;修改数据增强&#xff1b;validation增加mAP计算&#xff1b;修改anchor&#xff1b; 注: 实验开启weig…

HUAWEI 华为交换机 配置基于VLAN的MAC地址学习限制接入用户数量 配置示例

组网需求 如 图 2-15 所示&#xff0c;用户网络 1 通过 LSW1 与 Switch 相连&#xff0c; Switch 的接口为 GE0/0/1 。用户网络2通过 LSW2 与 Switch 相连&#xff0c; Switch 的接口为 GE0/0/2 。 GE0/0/1 、 GE0/0/2 同属于 VLAN2。为控制接入用户数&#xff0c;对 VLAN2 进…

蓝桥杯 最多约数

242*2*2*3&#xff08;质因子&#xff09;&#xff0c;约数&#xff08;11&#xff09;*&#xff08;11&#xff09;*&#xff08;11&#xff09;*&#xff08;11&#xff09;8 #include <bits/stdc.h> using namespace std; int main(){int a[700]{393353, 901440, 1234…

【React 报错】—Remove untracked files, stash or commit any changes, and try again.

【React 报错】—Remove untracked files, stash or commit any changes, and try again. 在react项目中通过.less文件进行样式定义&#xff0c;先暴露webpack配置文件&#xff0c;执行命令&#xff1a;yarn eject 或 npm run eject&#xff0c;报错如下&#xff1a; 原因是因…

第七十天 APP攻防-微信小程序解包反编译数据抓包APK信息资源提取

第70天 APP攻防-微信小程序&解包反编译&数据抓包&APK信息资源提取 知识点&#xff1a; 0、APK信息资源提取 1、微信小程序致据抓包 2、做信小程序解包反编译 1、信息收集应用8资产提取&权限等 2、漏润发现-反编泽&脱壳&代码审计 3、安全评估组件8散密…

李沐动手学习深度学习——3.2练习

以下是个人理解&#xff0c;希望进行讨论求解。 练习 1. 如果我们将权重初始化为零&#xff0c;会发生什么。算法仍然有效吗&#xff1f; 根据SGD算法公式如上&#xff0c;第一次迭代的值可知w只与b相关&#xff0c;而对于b的迭代更新&#xff0c;只是与b的初始值相关&#x…

【机器学习】线性回归模型(Linear Regression)

&#x1f338;博主主页&#xff1a;釉色清风&#x1f338;文章专栏&#xff1a;机器学习&#x1f338;今日语录:温柔的一半是知识&#xff0c;没有知识的涵养撑不起你想要的风骨。 ☘️0文章预览 本系列文章主要是根据吴恩达老师的机器学习课程以及自己的理解整合而成&#xf…

自动化操作读写Excel —— xlrd 和 xlwt 模块参数说明与代码实战【第95篇—自动化操作读写Excel 】

自动化操作读写Excel —— xlrd 和 xlwt 模块参数说明与代码实战 在日常工作中&#xff0c;Excel表格是不可或缺的数据处理工具。为了提高工作效率&#xff0c;Python中的xlrd和xlwt模块为我们提供了强大的功能&#xff0c;使得自动化操作Excel变得更加简便。本文将介绍xlrd和…

npm 最新淘宝镜像配置 + nrm工具配置及使用

一、前言 npm 淘宝镜像已经从 registry.npm.taobao.org 切换到了 registry.npmmirror.com &#xff08;HTTPS 证书到期不能用了&#xff09; 二、直接命令配置 1、执行以下命令即可切换淘宝源 npm config set registry https://registry.npmmirror.com/2、执行以下命令即可…

重拾前端基础知识:JavaScript

重拾前端基础知识&#xff1a;JavaScript 前言使用JavaScript输出语法运算符条件语句循环数据类型字符串数字数组对象日期函数 数学正则表达式异常处理类集合模块JSON闭包异步调试DOM&#xff08;文档对象模型&#xff09;事件事件监听器表单 BOM&#xff08;浏览器对象模型&am…

基于vue的图书管理系统的设计与实现

高校师生在教学中承受的压力越大就对知识拥有了更多的需求&#xff0c;而满足这一需求的最佳场所无疑就是图书馆。当前虽然信息技术在各个方面都发挥出重要作用&#xff0c;但是在相当多的高校图书馆中依然由工作人员手动完成图书借阅、归还及逾期提醒等所有工作&#xff0c;在…

03OpenCV图像的掩膜操作

文章目录 掩膜操作提高图像的对比度获取图像像素制作图像掩膜算子防止像素溢出算子全部代码 掩膜操作提高图像的对比度 红色是中心像素&#xff0c;从上到下&#xff0c;从左到右对每个像素做同样的处理操作&#xff0c;得到最终结果就是对比度提高之后的输出图像Mat对象 注&am…

【全志D1-H 哪吒开发板】Debian系统安装调教和点灯指南

全志D1-H开发板【哪吒】使用Deabian系统入门 特别说明&#xff1a; 因为涉及到操作较多&#xff0c;博文可能会导致格式丢失 其中内容&#xff0c;会根据后续使用做优化调整 目录&#xff1a; 参考资料固件烧录启动调教点灯问题 〇、参考资料 官方资料 开发板-D1开发板【…

NLP-词向量、Word2vec

Word2vec Skip-gram算法的核心部分 我们做什么来计算一个词在中心词的上下文中出现的概率&#xff1f; 似然函数 词已知&#xff0c;它的上下文单词的概率 相乘。 然后所有中心词的这个相乘数 再全部相乘&#xff0c;希望得到最大。 目标函数&#xff08;代价函数&#xff0…

本届挑战赛季军方案:基于图网络及LLM AGENT的微服务系统异常检测和根因定位方法

aiboco团队荣获本届挑战赛季军。该团队来自亿阳信通。 方案介绍 本届挑战赛采用开放式赛题&#xff0c;基于建行云龙舟运维平台的稳定性工具和多维监控系统&#xff0c;模拟大型的生活服务APP的生产环境&#xff0c;提供端到端的全链路的日志、指标和调用链数据。参赛队伍在组…

#LLM入门|Prompt#2.2_ AI 应用开发的范式_Language_Models,the_Chat_Format_and_Tokens

在本章中&#xff0c;我们将和您分享大型语言模型&#xff08;LLM&#xff09;的工作原理、训练方式以及分词器&#xff08;tokenizer&#xff09;等细节对 LLM 输出的影响。 我们还将介绍 LLM 的提问范式&#xff08;chat format&#xff09;&#xff0c;这是一种指定系统消息…

YOLOv8改进 | 独家创新篇 | 结合SOTA思想利用双主干网络改进YOLOv8(全网独家创新,最重磅的更新)

一、本文介绍 本文给大家带来的改进机制是结合目前SOTAYOLOv9的思想利用双主干网络来改进YOLOv8(本专栏目前发布以来改进最大的内容,同时本文内容为我个人一手整理全网独家首发 | 就连V9官方不支持的模型宽度和深度修改我都均已提供,本文内容支持YOLOv8全系列模型从n到x均可…

【STM32】STM32学习笔记-WDG看门狗(46)

00. 目录 文章目录 00. 目录01. WDG简介02. IWDG概述03. IWDG框图04. IWDG键寄存器05. WWDG简介06. WWDG框图07. WWDG工作特性08. IWDG和WWDG对比09. 预留10. 附录 01. WDG简介 WDG&#xff08;Watchdog&#xff09;看门狗 看门狗可以监控程序的运行状态&#xff0c;当程序因为…