ES6(三)——回调地狱和promise异步任务顺序执行(传参、错误处理)
文章目录
- 方法一、回调函数(回调地狱)
- 方法二:promise
- 2.1异步任务传参(单个)
- 2.2异步任务传参(多个)
- 2.3 错误处理
- 2.4 Promiss对象三大状态: (学名)
- 2.5 Promise.all()
- 2.6 Promise.race()
我们现在需要多个异步任务必须顺序执行
异步函数:各自执行各自的,互不干扰,互相之间也不会等待。
方法一、回调函数(回调地狱)
i. 前一项任务:
function 前一项任务(购物车){异步任务异步任务最后一句话之后购物车()
}
ii. 调用前一项任务时:
前一项任务(function(){ 下一项任务() })
示例:
// 下一项任务
function erya(next) { //异步console.log(`erya起跑!`);setTimeout(() => { //异步:在主程序外执行,主程序不会等它执行完console.log(`erya到达终点!`);// 之后,主动调用下一项任务next();}, 6000);
}function feifei(next) { //异步console.log(`feifei起跑!`);setTimeout(() => { console.log(`feifei到达终点!`);// 之后,主动调用下一项任务next();}, 4000);
}function bear() { //异步console.log(`bear起跑!`);setTimeout(() => { console.log(`bear到达终点!`);}, 2000);
}
// erya();
// feifei();
// bear();
erya(function() {yuan(function(){bear();});//yuan的next=function(){bear()}
})//erya的next=function(){yuan()}// 当erya执行完最后一句话,自调用erya的next:function(){yuan()},函数yuan开始执行
// 当yuan执行完最后一句话,自调用yuan的next:function(){bear()},函数bear开始执行
图解
①erya的推车装着yuan,yuan的推车装着bear。
第一段路erya推车跑,跑到终点:
②erya到达终点后,将自己的推车中的yuan和yuan的推车释放。
yuan从第二段路开始跑,跑到终点:
③yuan到达终点后,将自己推车中的bear释放,bear开始跑第三段路,直到终点
问题:回调地狱
按照以上方式,如果要先后执行的任务多了会形成很深的嵌套结构——我们称之回调地狱。
极其不优雅,极其不便于维护
方法二:promise
今后,只要多个异步任务必须顺序执行时,都要用promise技术来代替回调函数方式
步骤:
1). 定义前一项任务时:
调用return new Promise()
所在的异步任务函数,既可以执行异步函数的任务,又可以返回格子间
function 前一项任务(){return new Promise(// 赠function(开关){原异步任务异步任务最后一句话调用开关()//->通.then(),自动执行.then中的下一项任务})
}
2). 连接前后两个异步任务:
可用.then
与下一项任务串联
前一项任务().then( 后一项任务 )
多个异步任务串联:
任务1().then(任务2).then(任务3)
之后的任务一定不要加(),加()表示立刻执行。
而我们不希望后边的任务立刻执行
示例:
//promise
function erya() { //异步// 用new Promise(function(door)) {……}包裹原来的异步函数代码// 格子间 门return new Promise(function(door){console.log(`erya起跑!`);setTimeout(() => { console.log(`erya到达终点!`);// 在原异步函数的最后一行代码,主动调用door开门door();//自动执行.then()中串联的下一项任务}, 6000);})
}function yuan() { //异步return new Promise(function(door){console.log(`yuan起跑!`);setTimeout(() => { console.log(`yuan到达终点!`);door();}, 4000);})
}function bear() { //异步console.log(`bear起跑!`);setTimeout(() => { console.log(`bear到达终点!`);}, 2000);
}// .then之前必须是格子间对象,之后可以是格子间也可以是函数
erya().then(yuan).then(bear);
// 执行erya的任务,执行完,调用door()开门=>自动执行.then()中的yuan
图解:
①new Promise会创建一个关上门的格子间,附赠door(),调用door()可以开门
②且有一个钩子.then
,可以用来串联连接
.then
之前必须是格子间对象,之后可以是格子间也可以是函数
之后的任务一定不要加(),加()表示立刻执行。而我们不希望后边的任务立刻执行
2.1异步任务传参(单个)
利用door()进行传参,door默认只能传一个变量
步骤:
1.前一项任务:
function 前一项任务(){return new Promise(function(开关){var 变量=值原异步任务异步任务最后一句话调用开关( 变量 )//->通.then(),自动执行.then中的下一项任务})
}
2.后一项任务:
function 后一项任务(形参) {//形参=前一项任务中的变量值
}
示例:
function erya() {return new Promise(function(door) {var bang="接力棒";console.log(`erya拿着 ${bang} 起跑...`);setTimeout(function() {//异步console.log(`erya拿着 ${bang} 到达终点!`);door(bang);//自动执行.then()中串联的下一项任务}, 6000);})
}
function yuan(bang2) {//异步//bang2=erya中door()给的"接力棒"return new Promise(function(door) {console.log(`yuan拿着 ${bang2} 起跑...`);setTimeout(function() {//异步console.log(`yuan拿着 ${bang2} 到达终点!`);door(bang2); //通知.then中串联的下一项任务可以开始执行!}, 4000)})
}
function bear(bang3) {//异步//bang3=bear()中door()传来的"接力棒"console.log(`bear拿着 ${bang3} 起跑...`);setTimeout(function() {console.log(`bear拿着 ${bang3} 到达终点!`)}, 2000)
}erya().then(yuan).then(bear);
结果显示如图:
图解:
在第一个格子间对象中定义接力棒var bang=接力棒
,然后用door()传递接力棒bang,下一个格子间对象要定义一个形参bang2接收前一个传来的bang……以此类推
2.2异步任务传参(多个)
door中默认只能接收一个变量!
那么如果我们想要传递多个参数呢?
可以放在数组或对象中传递:
步骤:
1.前一项任务将door改为:
door([值1,值2,.…])
或者
door({属性1:值1,属性2:值2….. )
2.后一项任务: 参数解构
function下一项任务([形参1,形参2])
或者
function下一项任务({属性1,属性2})
示例:
function erya() {return new Promise(function(door) {var bang="接力棒";var drink = "水"console.log(`erya拿着 ${bang} 和${drink}起跑...`);setTimeout(function() {//异步console.log(`erya拿着 ${bang}和 ${drink}到达终点!`);door({bang, drink});//传入接力棒}, 6000);})
}
function yuan({bang, drink}) {//异步//bang2=erya中door()给的"接力棒"return new Promise(function(door) {console.log(`yuan拿着 ${bang} 和${drink}起跑...`);setTimeout(function() {//异步console.log(`yuan拿着 ${bang} 和${drink}到达终点!`);door({bang, drink}); //通知.then中串联的下一项任务可以开始执行!}, 4000)})
}
function bear({bang, drink}) {//异步//bang3=bear()中door()传来的"接力棒"console.log(`bear拿着 ${bang} 和${drink} 起跑...`);setTimeout(function() {console.log(`bear拿着 ${bang} 和${drink}到达终点!`)}, 2000)
}erya().then(yuan).then(bear);
2.3 错误处理
new Promise赠送了两个门: .
a. door,通往正常路线下一个.then
的门
b. err,通往出错路线下一个.catch
的门
1). 前一项任务:
function 前一项任务() {return new Promise(// 赠function(成功的开关, 失败的开关) {var 变量 = 值原异步任务异步任务最后一句话如果异步任务执行成功调用成功的开关( 变量 )//->通.then(),自动执行.then中的下一项任务否则如果一部任务执行失败调用失败的开关(错误提示信息)//->通最后的.catch(),后续.then()不再执行。})
}
2). 调用时:
前一项任务().then(下一项任务).then(...)
.catch(function(错误提示信息){ 错误处理代码
})
示例:
function erya() {// 赠两个门 正确 出错return new Promise(function(door,err) {var bang="接力棒";console.log(`erya拿着 ${bang} 起跑...`);setTimeout(function() {//异步//用随机数模拟出错的概率var r=Math.random();//0~1//假设r<0.6 60% 可以正常执行//如果没有摔倒if (r < 0.6) {console.log(`erya拿着 ${bang} 到达终点!`);//之后,主动调用door开门!door(bang);//自动执行.then()中串联的下一项任务} else {//否则如果摔倒了r>0.4 40%//走错误处理的门err("erya摔倒了!退赛!")}}, 6000)})
}
function yuan(bang2) {//异步//bang2=erya中door()给的"接力棒"return new Promise(function(door, err) {console.log(`yuan拿着 ${bang2} 起跑...`);setTimeout(function() {var r = Math.random();if (r<0.6) {console.log(`yuan拿着 ${bang2} 到达终点!`);door(bang2); //通知.then中串联的下一项任务可以开始执行!} else {//走错误处理的门err("yuan摔倒了!退赛!")}}, 4000)})
}
function bear(bang3){//bang3=yuan()中door()传来的"接力棒"console.log(`bear拿着 ${bang3} 起跑...`);setTimeout(function() {console.log(`bear拿着 ${bang3} 到达终点!`)}, 2000)
}erya().then(yuan).then(bear).catch(function(errMsg){console.error(errMsg);
})
2.4 Promiss对象三大状态: (学名)
当异步任务执行过程中,整个
new Promise()
对象处于 pending(挂起) 状态当异步任务成功执行完,调用成功的开关函数时,整个
new Promise()
对象切换为 fulfilled(成功) 状态,new Promise()会自动调用.then()
执行下一项任务当异步任务执行出错,调用失败的开关函数时,整个
new Promise()
对象切换为 rejected(出错) 状态,new Promise()会自动调用.catch()
执行错误处理代码
行业内:
1). 正确的开关: resolve 同意继续
2). 失败的开关: reject 拒绝继续
2.5 Promise.all()
const p=new Promise([p1,p2,p3])
p的状态由p1、p2、p3决定,分成两种情况:
(1)只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1、p2、p3的返回值组成一个数组(按数组顺序),传递给p的回调函数。
(2)只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。
1. all后的数组中每个格子间的异步任务都是并发执行的,谁也不等谁
2. all后的.then()
注定会等最慢的一个格子间执行完,才自动执行
function erya() {return new Promise(function(resolve){console.log(`erya起跑!`);setTimeout(() => { console.log(`erya到达终点!`);resolve();}, 6000);})
}
function yuan() { //异步return new Promise(function(resolve){console.log(`yuan起跑!`);setTimeout(() => { console.log(`yuan到达终点!`);resolve();}, 4000);})
}
function bear() { //异步return new Promise(function(resolve){console.log(`bear起跑!`);setTimeout(() => { console.log(`bear到达终点!`);resolve();}, 2000);})
}//希望三个人百米赛跑(谁也不等谁),但是最后一个人跑完时,才输出比赛结束!Promise.all([//只有调用异步函数,才能返回new Promise()格子间erya(),//return new Promise()//resolve()yuan(),//return new Promise()//resolve()bear()//return new Promise()//resolve()
]).then( function() { console.log("比赛结束!");
})
若传参,返回的数组:
顺序是按照all中数组的顺序
2.6 Promise.race()
Promise.race():
const p = Promise.race([p1, p2, p3]);
p1、p2、p3之中有一个实例率先改变状态,p的状态就跟着改变。
那个率先改变的Promise实例的返回值,就传递给p的回调函数。
Promise对象的特点
(1)对象状态不受外界干扰,Promise代表一个异步操作
(2)一旦状态改变,就不会再变,任何时候都可以得到这个结果
判断题:对于一个向后台获取数据已经产生结果的promise:p1,再次调用p1.then,不会去重新发起请求获取数据 √
ES6(三)——回调地狱和promise异步任务顺序执行(传参、错误处理)相关推荐
- 【JavaScript】回调地狱、Promise
文章目录 1. 回调函数 2. 异步任务 3. 回调地狱 4. Promise 4.1 Promise定义 4.2 Promise基础用法 4.2.1 生成Promise实例 4.2.2 Promis ...
- 详解回调地狱以及promise
1.什么是回调地狱? 说promise之前必须先简单说下,回调地狱 回调地狱:在回调函数中又嵌套了多层回调函数,便会形成回调地狱 JS中或node中,都大量的使用了回调函数进行异步操作,而异步操作什么 ...
- 回调地狱终结者——Promise
在Web前端开发中,我们使用JavaScript会大量依赖异步计算.比如说,Ajax请求时,我们可能会需要不只一个请求来达到某种目的,此时需要后面的请求依赖于前面请求的结果.这种情况在简单的业务中并无 ...
- 回调地狱和Promise
目录 1.回调地狱callback-hell 由于fs.readFile是异步操作,所以你不能判断下面三个文件的执行顺序 var fs = require('fs')fs.readFile('./da ...
- 回调地狱与promise
<script src="js/ajax.js"></script><script>// function fn(a){// a()// }// ...
- ES6 Promise 并行执行和顺序执行
1.Promise.all 并行执行promise getA和getB并行执行,然后输出结果.如果有一个错误,就抛出错误 /*** 每一个promise都必须返回resolve结果才正确* 每一个pr ...
- javascript --- 异步按顺序执行
使用promise可以很优雅的封装一个异步函数,使其按指定顺序执行: // 异步读取文件操作 const fs = require("fs"); function promiseR ...
- 异步API中promise解决回调地狱问题和异步函数async终极解决方案
- es6解决回调地狱问题
本文摘抄自阮一峰老师的 http://es6.ruanyifeng.com/#docs/generator-async 异步 所谓"异步",简单说就是一个任务不是连续完成的,可以理 ...
最新文章
- 2022-2028年中国肉制品行业市场调查研究及前瞻分析报告
- 【css】垂直居中的几种写法
- 5G NGC — 会话管理模型 — 边缘业务本地分流
- golang 结构体和数据库表字段 反射自动映射 sqlmapper库 简介
- 前端性能分析工具利器
- excel vba 从入门到精通_VBA词汇-基本元素篇
- 北京计算机一级2020,2020北京市一级计算机基础及MS Office应用考试在线自测试题库(不限设备,登陆即可做题)...
- c语言字符串匹配函数index,C语言(函数)学习之index、rindex
- 二级c语言统计小于n素数的个数,关于求N以内素数的一点小问题(N小于一亿)...
- 因为一条SQL,我差点被祭天......
- 3d打印英语文献_3D打印模型在腹腔镜肝胆微创手术术前培训中的应用
- 【例题4-2 uva489】Hangman Judge
- 如何让电脑的多个蓝牙音响同时输出声音
- js版的倒计时(月-日-时-分-秒-毫秒)
- python重启路由器_Python实现路由器的重启和查看实时流量
- Ubuntu 18.04 Bionic Beaver Linux上安装TeamViewer
- kaggle数据分析入门之---视频游戏销售分析
- rx580和gtx1650哪个好
- linux 时区 0900是哪,c#-解析DateTime的时区为PST / CEST / UTC /
- python 算法教程 pdf 英文_上手实践《Python机器学习第2版》PDF中文+PDF英文+代码+Sebastian...
热门文章
- maven release插件将一版本发布到仓库中时Return code is: 401, ReasonPhrase:Unauthorized
- 安卓+servlet+MySql 查询+插入(汉字乱码解决)
- JPEG2000开发SDK及其特点
- [Node.js] 基于NodeJS+Express+mongoDB+Bootstrap的博客系统实战
- node-gulp插件
- Node.js-json-模块化-全局对象-fs-服务-Buffer
- 非极大值抑制(NMS)
- 机器学习算法(7)——K近邻(KNN)、K-means、模糊c-均值聚类、DBSCAN与层次与谱聚类算法
- java框架ssh实验报告_基于SSH的实验报告提交系统
- html 自动跳转到不同页面,html跳转到同一个页面的不同位置_html/css_WEB-ITnose