接上Promise()对象处理回调地狱:怎么用.then()?什么是Async、Await?

上一篇基于JavaScript基础的异步、同步操作,promise、.then()-CSDN博客讲了【啥是异步操作、同步操作?】然后简单讲了回调函数是啥、Promise()对象是啥、.then()函数是啥,这一篇讲讲promise()对象到底怎么配合.then()函数解决回调地狱,还有Async、Await又是啥。

一、最简单的方式了解怎么用【Promise对象配合.then()】解决回调地狱

1、首先回顾一下Promise对象配合.then()的用法,一张图看明白

2、接下来,我们找个回调地狱的例子:

假设我要依次隔1秒输出【广东省】->【阳江市】->【阳东区】->【东城镇】

先按蠢方法

这样写看得人眼睛都花了,这啥啊?老方法的.then()就是不断创建新的Promise对象,然后把resoleve()成功函数里把上一个【成功的结果】拼上【新的成功结果】传出去,传到下一个.then()函数里,依次反复,估计我讲这么多没人会看,也没人看懂,那么我们跳过

3、现在我们优化一下,怎么搞?简单理解:

1、.then()函数是怎么获取到resolve()成功函数的结果的?只要Promise对象设置了resolve()成功函数,然后Promise对象自己调用自己的.then()回调函数,这个回调函数的参数自动就接收【resolve()成功函数】的传出去的参数结果

2、那么第一步必须得有一个Promise对象,里面照上面操作设置resolve、reject函数并往里传入像输出的结果作为参数,然后在外面用Promise对象.then()输出结果

const p = new Promise(( resolve, reject ) => {
    resolve('成功的结果')
    reject(new Error('错的提示'))
})

p.then(res=>{
    //拿到第一个‘成功的结果’
})

3、第三步重要了!!很简单,你在这个.then()函数里return一下结果,这个结果不就可以传出去给别人用了吗?然后在这个.then()后面再接一个.then()函数,刚刚return的结果就给到下一个.then()函数了,它再拿到上一个的结果,跟上自己的结果return给下一个,下下个.then()又接到它return的

p.then(res=>{
    return 结果
}).then(res=>{
    return 结果
}).then(res=>{
    return 结果
})
......

4、然后注意一点,我们不是简单return个【结果】就行了,你要一直用.then()函数的话,要想一想.then()是谁的函数?要Promise对象才可以调用.then()啊,而且.then()接收的结果也是来自Promise对象的resolve成功函数传出的结果,总而言之!你return的东西应该是一个【Promise对象】!!!!

你把【包含了要输出的结果】的【Promise对象】return出去,然后这个【Promise对象】调用.then(),再接着把【包含了要输出的结果】的【Promise对象】return出去

最后优化结果是这样:

代码在这:

const p = new Promise(( resolve, reject ) => {
    setTimeout(()=>{
        resolve('广东省')
        reject(new Error('错了'))
    },1000)
})

p.then(res=>{
    return new Promise(( resolve, reject ) => {
        setTimeout(()=>{
            resolve(res + '阳江市')
            reject(new Error('错了'))
        },1000)
    })
}).then(res=>{
    return new Promise(( resolve, reject ) => {
        setTimeout(()=>{
            resolve(res + '阳东区')
            reject(new Error('错了'))
        },1000)
    })
}).then(res=>{
    return new Promise(( resolve, reject ) => {
        setTimeout(()=>{
            resolve(res + '东城镇')
            reject(new Error('错了'))
        },1000)
    })
}).then(res=>{
    console.log(res)
})

二、如果上面的你理解起来还是很头晕,那么现在来了解【Async】、【Await】是什么

上面的例子还是要一会又return,一会又.then(),哪个结果对应到哪个.then()函数,一时还真不好找,那么现在有这两个东西修改一下写法:【Async】、【Await】

【Async】:不用去查那么复杂的解释,简单理解就是【异步函数】,任何函数前面加了Async关键字,那就是一个【Async异步函数】

【Await】:Await函数就是等待一个Promise对象兑现成功或失败后,把resolve或reject的结果值返回给Await,说白了他就是.then()的替身,它来获取Promise对象的结果。用它的条件:1、必须有Promise实例   2、必须在【异步函数里】,也就是只能在【Async函数】里用

总结:它两配合起来就可以写出看着像【同步操作】写法的【异步操作】,会舒服一点

那怎么用?

1、第一步,把你要有先后次序的这些事情分别写在不同的函数里,然后这些函数要这些事情、结果输出,就要return一个包含这些结果的Promise对象,这样await就可以调用并获得这些函数结果

function A(){
    return new Promise(( resolve, reject ) => {
        setTimeout(()=>{
            resolve('广东省')
            reject(new Error('错了'))
        },1000)
    })
}
function B(){
    return new Promise(( resolve, reject ) => {
        setTimeout(()=>{
            resolve('阳江市')
            reject(new Error('错了'))
        },1000)
    })
}
function C(){
    return new Promise(( resolve, reject ) => {
        setTimeout(()=>{
            resolve('阳东区')
            reject(new Error('错了'))
        },1000)
    })
}
function D(){
    return new Promise(( resolve, reject ) => {
        setTimeout(()=>{
            resolve('东城镇')
            reject(new Error('错了'))
        },1000)
    })
}

2、第二步,因为await函数需要在【异步函数】里,那么async就是异步函数,那就是用async声明的一个函数包住await函数就行了,最后别忘了调用执行这个async函数

async function fn(){
    const res = await A()
    console.log(res)

    const resB = await B()
    console.log(resB)

    const resC = await C()
    console.log(resC)

    const resD = await D()
    console.log(resD)
}

//最后别忘了调用执行这个async函数,上面只是声明函数
fn()

现在你看,是不是能很清晰的看出哪个结果来自哪个函数了

三、这两玩意广泛用于获取axios网络请求返回的结果

axios和Promise

学过ajax的知道axios库是一个发送网络请求的HTTP客户端,它的底层原理就是基于在一个【Promise对象】里创建一个【XMLHttpRequest对象】,然后把传给axios库的服务器网址参数传给自己函数里的【Promise对象】的【XMLHttpRequest对象】,进行发送请求,然后把请求成功的结果或失败的结果,通过【Promise对象】return出去

这里给大伙看一个自己手动创建一个本地axios库的例子方便大家理解

function MyAxios(config){
    return new Promise(( resolve , reject ) => {
        //创建XMLHttpRequest()对象来发送请求
        const xhr = new XMLHttpRequest()
        //这里直接用对象的属性来open(), “对象形参.method”如果没有设置就是undefined,那么就自动选'请求方式',然后url也用下面调用时传的对象参数的属性就行
        xhr.open(config.method || 'get' , config.url)
        xhr.addEventListener('loadend',function(){
            //通过状态码来判断是成功还剩失败,状态码一般200多的就是成功,所以只要>=200 && < 300就行
            if(xhr.status >= 200 && xhr.status < 300){
                resolve(JSON.parse(xhr.response))//请求成功结果
            }else{
                reject(new Error(xhr.response))//请求失败结果
            }
        })
        xhr.send()
    })
}

MyAxios({
    url: 'https://hmajax.itheima.net/api/province',            
}).then(res => {
    console.log(res)
}).catch(err => {
    document.querySelector('.myP').innerHTML = err.message
})

所以我们学axios库的时候,才会用axios()库去调用.then()、.catch()函数,因为axios库函数它return的就是【Promise对象】,也就是一个【Promise对象】在用.then()、.catch()方法。

既然如此,那么用【async】和【await】也同样可以

现在我们知道axios就是基于Promise对象的,那么当使用axios发送请求时,就会返回一个Promise对象,然后【await函数】就可以等待Promise对象兑现结果之后,获取到它的成功或失败的结果,然后在搭配async函数,完美,这样就可以获得axios库返回的结果了,不用.then()和.catch()了

async function fn(value){
    //设一个变量接收await获取到的axios返回的网络请求结果
    const res = await axios({
        url: 'https://applet-base-api-t.itheima.net/api/translate',
        params: {
            words: value
        }
    })

    console.log(res)
}

fn('damn')

讲完了,要是还看不懂,那你就转行吧,没希望了兄弟

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

学习和工作的投入产出比(节选)

人工智能统领全文 推荐包含关于投入、产出、过剩、市场关注、案例、结果和避雷等主题的信息&#xff1a; 投入与产出&#xff1a; 投入和产出都有直接和间接两类常见形式。常见的四种组合是&#xff1a;直接投入、直接产出、间接投入、间接产出。 过剩&#xff1a; 过剩是一个重…

QtCreator报Failed to parse qmlimportscanner output解决

错误如下: 定位错误位置 增加错误信息打印 打印执行命令 执行打印输出的命令,成功返回JSON 但输出的JSON对象不是json格式,而是命令 增加$$成功输出JSON 使用QtCreator12编译一次后,再使用QtCreator13成功编译通过,问题解决

如何实现WordPress后台显示文章、分类目录、标签等的ID?

我们平时在使用WordPress的过程中&#xff0c;偶尔需要用到文章的ID&#xff0c;或分类目录ID&#xff0c;或标签ID&#xff0c;或媒体库ID&#xff0c;或评论ID&#xff0c;或用户ID等&#xff0c;但是WordPress后台默认是不显示它们的ID的。 今天boke112百科就跟大家分享如何…

刷题第3天(简单题):LeetCode203--移除链表元素--虚拟头结点

LeetCode203:给你一个链表的头节点 head 和一个整数 val &#xff0c;请你删除链表中所有满足 Node.val val 的节点&#xff0c;并返回 新的头节点 。 示例 1&#xff1a; 输入&#xff1a;head [1,2,6,3,4,5,6], val 6 输出&#xff1a;[1,2,3,4,5]示例 2&#xff1a;输入…

vue3中的ref和reactive的区别

vue3中的ref和reactive的区别 1、响应式数据2、ref3、reactive4、ref VS reactive5、往期回顾总结&#xff1a; 1、响应式数据 处理响应式数据时到底是该用ref还是reactive... 响应式数据是指在 Vue.js 中&#xff0c;当数据发生变化时&#xff0c;相关的视图会自动更新以反映…

纯css实现-让字符串在文字少时显示为居中对齐,而在文字多时显示为左对齐

纯css实现-让字符串在文字少时显示为居中对齐&#xff0c;而在文字多时显示为左对齐 使用flex实现 思路 容器样式&#xff08;.container&#xff09;: Flex容器的BFC性质使得其内部的子元素&#xff08;.text-box&#xff09;在水平方向上能够居中&#xff0c;通过justify-c…

用node写后端环境运行时报错Port 3000 is already in use

解决方法:关闭之前运行的3000端口,操作如下 1.WindowR输入cmd确定,打开命令面板 2.查看本机端口详情 netstat -ano|findstr "3000" 3.清除3000端口 taskkill -pid 41640 -f 最后再重新npm start即可,这里要看你自己项目中package.joson的启动命令是什…

简单版 git快速上手使用 clone项目 新建/切换分支 提交修改

Git是一个广泛使用的版本控制系统&#xff0c;允许多个用户跟踪文件的更改&#xff0c;并协作开发项目。 首先确定自己电脑已经安装了git&#xff0c;具体安装步骤请查找教程&#xff0c;应该不难。 以windows电脑为例&#xff0c;安装完后在搜索栏搜索git会出现 先解释一下这…

B端系统用户体验最高原则:美观与易用的结合,附大波案例

将美观与易用结合是B端系统用户体验的最高原则&#xff0c; 强调美观忽视易用&#xff0c;那是反人类设计&#xff1b;强调易用忽视美观&#xff0c;那是泯灭人性的设计。本文分享为什么系统要结合二者&#xff0c;欢迎关注点赞&#xff0c;如有需求&#xff0c;可以私信我们。…

租床小程序|租床系统|租赁软件开发功能

随着移动互联网的普及&#xff0c;越来越多的人开始选择在线上完成各种租赁业务&#xff0c;而医院租床也不例外。在这个趋势下&#xff0c;开发一款租赁小程序成为了市场的必然需求。 租床小程序的功能 1、搜索与筛选 为了满足不同用户的需求&#xff0c;小程序应该提供设备…

3/1作业

1.用fwrite和fread将任意bmp图片&#xff0c;修改成德国的国旗 #include <stdio.h> #include <string.h> #include <unistd.h> #include <stdlib.h> int main(int argc, const char *argv[]) { FILE* fp fopen("1.bmp","r")…

Timeplus-proton流处理器调研

概念 Timeplus是一个流处理器。它提供强大的端到端功能&#xff0c;利用开源流引擎Proton来帮助数据团队快速直观地处理流数据和历史数据&#xff0c;可供各种规模和行业的组织使用。它使数据工程师和平台工程师能够使用 SQL 释放流数据价值。 Timeplus 控制台可以轻松连接到不…

Javaweb之SpringBootWeb案例之 Bean管理的Bean作用域详细的解析

2.2 Bean作用域 在前面我们提到的IOC容器当中&#xff0c;默认bean对象是单例模式(只有一个实例对象)。那么如何设置bean对象为非单例呢&#xff1f;需要设置bean的作用域。 在Spring中支持五种作用域&#xff0c;后三种在web环境才生效&#xff1a; 作用域说明singleton容器…

使用Docker搭建一款实用的个人IT工具箱——It-Tools

作为程序员&#xff0c;在日常工作中&#xff0c;需要借助一些工具来提高我们工作效率&#xff0c;IT-Tools是为开发人员度身打造的一套便捷在线工具。它提供全面功能&#xff0c;使开发者能以更高效方式完成任务。经由IT-Tools&#xff0c;开发人员能轻松应对各类技术挑战&…

yolov9 tensorRT 的 C++ 部署

yolov9 tensorRT C 部署 本示例中&#xff0c;包含完整的代码、模型、测试图片、测试结果。 完整的代码、模型、测试图片、测试结果【github参考链接】 TensorRT版本&#xff1a;TensorRT-7.1.3.4 导出onnx模型 导出适配本实例的onnx模型参考【yolov9 瑞芯微芯片rknn部署、地平…

Consul服务注册与发现 Consul配置步骤

Consul服务注册与发现 Consul配置步骤 consul下载地址 Install | Consul | HashiCorp Developer 启动需要在 下载好的文件夹里 用cmd 运行consul agent -dev启动consul Consul配置 配置pom <!--SpringCloud consul config--> <dependency><groupId>org…

基于JSON的Ollama和LangChain agent

到目前为止&#xff0c;我们都可能意识到&#xff0c;通过为LLMs提供额外的工具&#xff0c;我们可以显著增强它们的功能。 例如&#xff0c;即使是ChatGPT在付费版本中也可以直接使用Bing搜索和Python解释器。OpenAI更进一步&#xff0c;为工具使用提供了经过优化的LLM模型&am…

综合练习(二)

目录 列出薪金比 SMITH 或 ALLEN 多的所有员工的编号、姓名、部门名称、领导姓名、部门人数&#xff0c;以及所在部门的平均工资、最高和最低工资 补充 spool Oracle从入门到总裁:https://blog.csdn.net/weixin_67859959/article/details/135209645 列出薪金比 SMITH 或 AL…

我国每年研究生的毕业数量统计分享

本数据集详细记录了自1949年至2021年我国每年研究生的毕业数量&#xff08;包括硕士和博士学位的毕业生&#xff09;。在2021年&#xff0c;我国的研究生毕业生人数达到了772,761人&#xff0c;此数字比上一年度增加了44,000人。 统计的数据单位使用的是人数。 数据展示&…

C语言--修饰符(auto、extern、static)与变量(局部变量+全局变量)和函数的关系

其中extern功能和用法上&#xff0c;比较特殊。先了解extern修饰全局变量&#xff0c;我总结为以下几点 为了方便描述&#xff0c;我创建了一个工程&#xff0c;工程包含了两个源文件&#xff0c;main.c和database.c **1&#xff09;&#xff1a;database.c中使用extern时用来…