回调函数、回调地狱、解放方法Promise的用法

回调函数

回调函数的定义非常简单:一个函数被当做一个实参传入到另一个函数(外部函数),并且这个函数在外部函数内被调用,用来完成某些任务的函数。就称为回调函数

回调函数的两种写法(实现效果相同):

const text = () => {document.write('hello james')
}
setTimeout(text,1000)
setTimeout(()=>{document.write("hello james")
},1000)

这段代码中的 setTimeout 就是一个消耗时间较长的过程,它的第一个参数是个回调函数,第二个参数是毫秒数,这个函数执行之后会产生一个子线程,子线程会等待 1 秒,然后执行回调函数 “text”,在文本中输出hello james

setTimeout会在子线程中等待1秒,但是主线程的运行不会受到影响!例如以下代码:

setTimeout(()=>{document.write("hello davis")
},1000)
console.log('123456');

回调地狱

回调地狱这个词听起来就非常的高大上,想要接触Promise之前,必须要懂得什么是回调地狱,以及为什么会产生回调地狱?
先来看看概念:当一个回调函数嵌套一个回调函数的时候就会出现一个嵌套结构当嵌套的多了就会出现回调地狱的情况。
举个例子:
比如我们发送三个 ajax 请求:

第一个正常发送
第二个请求需要第一个请求的结果中的某一个值作为参数
第三个请求需要第二个请求的结果中的某一个值作为参数

你会看到以下代码:

$.ajax({url: '我是第一个请求',type: 'get',success (res) {// 现在发送第二个请求$.ajax({url: '我是第二个请求'type:'post',data: { a: res.a, b: res.b },success (res1) {// 进行第三个请求$.ajax({url: '我是第三个请求',type:'post',data: { a: res1.a, b: res1.b },success (res2) { console.log(res2) }})}})}
})

Promise

Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大,它是一个 ECMAScript 6 提供的类,目的是更加优雅地书写复杂的异步任务。

Promise对象有以下两个特点:

1、 对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是Promise这个名字的由来,它的英语意思就是“承诺”,表示其他手段无法改变。

2、一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved(已定型)。如果改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。

两个特点摘自于😛😛阮一峰ES6文章😛😛

  • Promise语法格式
new Promise(function (resolve, reject) {// resolve 表示成功的回调// reject 表示失败的回调
}).then(function (res) {// 成功的函数
}).catch(function (err) {// 失败的函数
})

出现了new关键字,就明白了Promise对象其实就是一个构造函数,是用来生成Promise实例的。能看出来构造函数接收了一个函数作为参数,该函数就是Promise构造函数的回调函数,该函数中有两个参数resolve和reject,这两个参数也分别是两个函数!

简单的去理解的话resolve函数的目的是将Promise对象状态变成成功状态,在异步操作成功时调用,将异步操作的结果,作为参数传递出去。reject函数的目的是将Promise对象的状态变成失败状态,在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。

Promise实例生成以后,可以用then方法分别指定resolved状态和rejected状态的回调函数。

代码示例:

    const promise = new Promise((resolve,reject)=>{//异步代码setTimeout(()=>{// resolve(['111','222','333'])reject('error')},2000)})promise.then((res)=>{//兑现承诺,这个函数被执行console.log('success',res);}).catch((err)=>{//拒绝承诺,这个函数就会被执行console.log('fail',err);})

代码分析:

上边说到Promise是一个构造函数,new之后等于说调用了构造函数,构造函数中传的参数是一个函数,这个函数内的两个参数分别又是两个函数(reslove和reject),虽然感觉很绕,但是理清思路会很清晰的!我们得到对象promise,promise对象中自带有两个方法then和catch,这两个方法中会分别再传入一个回调函数,这个回调函数的目的在于返回你所需要成功或失败的信息!那么怎么去调用这两个回调函数呢?
看下方图可以快速理解:

在这里插入图片描述
这两个函数分别做为参数(reslove和reject)传到上方的函数中去了.随后在构造函数的回调函数中写入异步代码(例如:ajax和定时器),这里使用了定时器作为例子,如果你想表达的是成功回调,你可以在内部调用函数reslove('一般情况下是后端返回的成功数据)。如果你想表达的是失败回调,你可以调用reject(‘一般情况下是后端返回的失败信息’).

这些就是Promise执行的过程!虽然理解着很绕,但是多读几遍绝对有不一样的收获!

Promise链式

then方法返回的是一个新的Promise实例(注意:不是原来那个Promise实例)。因此可以采用链式写法,即then方法后面再调用另一个then方法
实际案例:
我想要实现在一个数组中查看一个帖子,但是我最终的目的是得到这个帖子下面的所有评论,这该怎么实现呢?

实现思路:
先从一个接口中获取这个帖子的信息,然后通过该帖子的帖子id从而获取到该帖子下的所有评论

代码如下:


pajax({url:"http://localhost:3000/news",data : {author : "james"}
}).then(res=>{return pajax({url : "http://localhost:3000/comments",data : {newsId : res[0].id}})
}).then(res=>{console.log(res);
}).catch(err=>{console.log(err);
})

代码分析:

这里使用了一个Promise已经封装过的ajax,我们从第一个接口中得到了帖子id,然后在then中的函数发送第二个请求(携带了第一个请求返回过来的参数),我们最后想要拿到第二个接口的结果,于是又有了一个then方法,但是在第一个then方法中要把一个新的Promise实例return出去,这样的话,第二个then才起作用!(这是因为then方法是Promise 实例所具有的方法,也就是说,then方法是定义在原型对象Promise.prototype上的)====>我们可以打印一下:console.log(Promise.prototype)
在这里插入图片描述

可以看的出来原型对象Promise.prototype中是有then方法的!

Promise.all()

Promise.all()方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。

语法格式:

const p = Promise.all([p1, p2, p3]);

Promise.all()方法接受一个数组作为参数,p1、p2、p3都是 Promise 实例,如果不是,就会调用Promise.reslove() [该方法可自行了解]自动将参数转为 Promise 实例,再进一步处理。
说那么多白话没用,我们可以根据一个案例,就可以明白Promise.all()的用途了。

实际案例:
如果你想实现一个效果:在一个页面中,等到页面中所有的请求返回数据后,再渲染页面,该怎么实现呢?(在实际开发中我们会看到loading加载页面,等数据返回完后,loading加载页面会消失,整个页面就展现出来了,增强用户的体验。)

实现思路:
通过Promise.all()方法,等多个接口全部接收到数据后,再统一进行处理,然后渲染页面

代码如下:

console.log("显示加载中")
const q1 = pajax({url:"http://localhost:3000/looplist"
})const q2 = pajax({url:"http://localhost:3000/datalist"
})
Promise.all([q1,q2]).then(res=>{console.log(res)console.log("隐藏加载中...")
}).catch(err=>{console.log(err)
})

代码分析:

在上方代码中,全局打印显示加载中是代替loading的页面,表示该页面现在正是loading页面中,等到q1和q2所请求接口都得到返回的信息后,在then方法中接收收据,并且可以进行渲染页面,同时隐藏了loading加载页面!

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

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

相关文章

个人项目介绍4:三维园区篇

个人项目介绍: 地图铁路线路篇 地球卫星篇 火车站篇 三维园区篇 项目需求: 1.按比例全景显示三维园区 2.精确显示园区内设备设施 3.实时显示设备报警信息 4.显示园区内摄像监控设备,并可点击显示监控视频流 5.显示园区内的重大危险源和风险分布 …

PCL 路面点云标线提取(C++详细过程版)

目录 一、算法原理二、代码实现三、结果展示本文由CSDN点云侠原创,原文链接。如果你不是在点云侠的博客中看到该文章,那么此处便是不要脸的爬虫与GPT。 一、算法原理 算法来自本人自创。实现效果如下图所示,具体实现原理看代码即可。 二、代码实现 #include

bean的管理方式

默认情况下,spring项目启动时,会把bean对象全部创建好放到ioc容器 主动获取bean对象:getBean里面传入bean的名称或bean的类型 注意如果没有主动设置bean的名称,则默认名称是对应类名的首字母小写 在ioc容器中,bean对…

今天分享一个好看的输入法皮肤相信每个人心里住着一个少女心我们美化一下她吧

标题: 白日梦皮肤上线,百度输入法助你开启梦幻之旅! 正文: 大家好呀!今天我来给大家安利一款超级梦幻的百度输入法皮肤——“白日梦”系列! 这款皮肤的设计灵感来源于我们内心深处的白日梦,充…

14. C++继承与虚函数

【继承基础概念】 继承可以让本类使用另一个类的非私有成员,提供共用成员的类称为父类或基类,使用共用成员的类称为子类或派生类,子类创建对象时会包含继承自父类的成员。 继承的优势是减少重复定义数据,当本类需要在另一个类的…

L1-009 N个数求和

MD...提交过了好几次才通过。 第三个测试点: 需要使用long long,要求长整型。干脆就把int全部替换成long long。 第五个测试点: 随便试出来的,我输入了2 1/2 -1/2,发现啥都没打印出来。原来是忽略了结果是0的情况,如果整数部分和分子部分都…

LabVIEW高温摩擦磨损测试系统

LabVIEW高温摩擦磨损测试系统 介绍了一个基于LabVIEW的高温摩擦磨损测试系统的软件开发项目。该系统实现高温条件下材料摩擦磨损特性的自动化测试,通过精确控制和数据采集,为材料性能研究提供重要数据支持。 项目背景 随着材料科学的发展,…

git revert 撤回之前的几个指定的提交

文章目录 Intro操作命令-n 选项 参考 Intro 在开发过程中,有的时候一开始只是一个小需求,可以改着改着事情超出了控制,比如说我一开始只是想调整一个依赖包的版本,可是改到后来类库不兼容甚至导致项目无法启动。 这个时候我就想&…

npm市场发布包步骤

1.打开npm官网npm官网 2.创建自己的账号 3.查看当前npm的镜像源, 如果出现淘宝的镜像源则需要切换成官方的镜像源 npm config get registry //查看镜像源 https://registry.npm.taobao.org/ //淘宝的镜像源 https://registry.npmjs.org/ //官方的镜像源 …

Linux文本处理三剑客:awk(常用匹配模式)

在Linux操作系统中,grep、sed、awk被称为文本操作“三剑客”,上三期中,我们将详细介绍grep、sed、awk的基本使用方法,希望能够帮助到有需要的朋友。 1、前言 awk作为一门编程语言还有很多内容,我们继续学习awk。 网…

线程安全之死锁

目录 一、概念 二、例子 三、死锁相关面试题目 一、概念 死锁主要发生在有多个依赖锁存在时,会在一个线程试图以另一个线程相反顺序锁住互斥量时发生 死锁使得一个或多个线程被挂起而无法继续执行,最糟糕的是,这种情况还不容易被发现。 在一个线程中对一个已经加锁的普通锁…

根据标准化开发流程---解析LIN总线脉冲唤醒的测试方法和用例设计思路

前言:本文从标准化开发流程的角度,以LIN总线脉冲唤醒为切入点。从测试工程师的角度来讲测试工作应当如何展开(结合我干测试总结出来的测试经验)。希望大家都能从中有收获!!谢谢!! 1…

FreeROTS day2

总结DMA空闲中断接收数据的使用方法 首先要要选择串口然后配置串口的参数,配置MDA通道选择接受数据,配置空闲中断,定义一个数据接收的容器,启动MDA传输当串口收到数据时MDA将数据传输到容器中,MDA会一直检测是否有数据当有数据并…

【蓝桥杯基础算法】dfs(上)组合数,全排列

刚接触算法&#xff0c;有没有被递归又循环的dfs吓到&#xff1f;没关系&#xff0c;几个例题就可以彻底掌握&#xff01; 1.全排列 1-n的全排列,如输入3&#xff0c;按顺序对1-3进行排列 //枚举 #include<iostream> #include<algorithm> #include<cstring>…

[动态规划][蓝桥杯 2022 省 B] 李白打酒加强版 -- 代码注释含详解

P8786 [蓝桥杯 2022 省 B] 李白打酒加强版(洛谷) 洛谷题目链接 李白打酒很快活&#xff0c;而我打了一晚上代码才把这题弄懂&#x1f972; P8786 [蓝桥杯 2022 省 B] 李白打酒加强版(洛谷)题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 提示\***\*\*\*\*\***\*\*\**…

-bash: unzip: 未找到命令的解决方案

遇到 -bash: unzip: 未找到命令 这样的错误信息&#xff0c;表示你的系统中没有安装 unzip 工具。unzip 是一个常用的解压工具&#xff0c;用于解压缩 .zip 文件。你可以通过系统的包管理器安装它。 根据你使用的 Linux 发行版&#xff0c;安装 unzip 的命令会有所不同。下面是…

MUMU模拟器12连logcat的方法

大家好&#xff0c;我是阿赵。   在开发手机游戏的时候&#xff0c;在真机上会出现各种问题&#xff0c;在查询问题的时候&#xff0c;安卓手机需要用adb连接来连接手机看logcat输出分析问题。但由于连接手机比较麻烦&#xff0c;所以我都习惯在电脑用安卓模拟器来测试。   …

通过vue ui创建项目

确认前端环境都安装好之后 打开黑窗口 输入 vue ui 会打开一个vue的网页 在此创建项目 可以选择在那个路径创建 这是我的项目配置 这里是选择vue版本 我要用的是vue2 选好点击创建项目就好了 创建好后的重点的目录结构以及结构的作用 启动前端工程 将创建好的项目导入编译器 我…

跨境干货 | 想“躺平式”经营?TikTok Shop全托管模式入驻了解一下!

在当前跨境电商出海模式不断升级的背景下&#xff0c;全托管模式已经成为各类平台的标准配置。其中&#xff0c;TikTok全托管模式已经上线运行有很长一段时间了&#xff0c;这个模式下&#xff0c;主打一个“仅供货、免运营”&#xff0c;它降低了商家进入和运营TikTok市场的门…

liunx操作系统 环境变量

环境变量 main函数参数 命令行参数环境变量 环境变量的查看环境变量的获取 main函数参数 命令行参数 main函数是有参数的&#xff0c;只是我们一般不适用 这是main函数从bash中读取进程数据使用的一个基本入口。 下面进行简单演示。 o 好oo都是我们输入的命令行参数。其实&a…