当前位置:网站首页>回调地狱和promise
回调地狱和promise
2022-08-11 11:52:00 【-加油】
根据setTimeout的延迟时间,会依次执行奶茶、火锅、唱歌、看电影。这不是我想要的顺序。
function getTea(fn){
setTimeout(()=>{
fn('奶茶')
},500)
}
function getHotpot(fn){
setTimeout(()=>{
fn('火锅')
},600)
}
function getSing(fn){
setTimeout(()=>{
fn('唱歌')
},700)
}
function getfilm(fn){
setTimeout(()=>{
fn('看电影')
},1000)
}
//统一处理数据的方法
function fn(data){
console.log(data);
}
getfilm(fn)
getSing(fn);
getHotpot(fn);
getTea(fn);
我想先看电影,唱歌、火锅、奶茶,就需要一层一层嵌套实现。就会造成可怕的回调地狱,层数越多维护起来越麻烦。
function getTea(fn){
setTimeout(()=>{
fn('奶茶')
},500)
}
function getHotpot(fn){
setTimeout(()=>{
fn('火锅')
},600)
}
function getSing(fn){
setTimeout(()=>{
fn('唱歌')
},700)
}
function getfilm(fn){
setTimeout(()=>{
fn('看电影')
},1000)
}
getfilm(function(data){
console.log(data);
getSing(function(data){
console.log(data);
getHotpot(function(data){
console.log(data);
getTea(function(data){
console.log(data);
})
})
})
})
办法:使用promise解决异步问题,比回调地狱更好维护。
//每个函数调用后返回的都是promise对象
function getTea(){
return new Promise(function(resolve){
setTimeout(()=>{
//调用resolve把数据传出去
resolve('奶茶')
},500)
})
}
//每个函数调用后返回的都是promise对象
function getHotpot(){
return new Promise(function(resolve){
setTimeout(()=>{
resolve('火锅')
},600)
})
}
//每个函数调用后返回的都是promise对象
function getSing(){
return new Promise(function(resolve){
setTimeout(()=>{
resolve('唱歌')
},700)
})
}
//每个函数调用后返回的都是promise对象
function getfilm(){
return new Promise(function(resolve){
setTimeout(()=>{
resolve('看电影')
},1000)
})
}
// getfilm(); 返回值是一个promise对象 直接用then
getfilm().then(function(data){
console.log(data);
//then 里面写一个return 一个还想调的promise对象
return getSing();
}).then(function(data){
console.log(data);
return getHotpot();
}).then(function(data){
console.log(data);
return getTea();
}).then(function(data){
console.log(data);
})
可是看起来也没有化繁为简,一堆的then。
使用async函数
function getTea(){
return new Promise(function(resolve){
setTimeout(()=>{
//调用resolve把数据传出去
resolve('奶茶')
},500)
})
}
function getHotpot(){
return new Promise(function(resolve){
setTimeout(()=>{
resolve('火锅')
},600)
})
}
function getSing(){
return new Promise(function(resolve){
setTimeout(()=>{
resolve('唱歌')
},700)
})
}
function getfilm(){
return new Promise(function(resolve){
setTimeout(()=>{
resolve('看电影')
},1000)
})
}
//将异步实现效果为同步
async function fn(){
//getfilm() 返回值是promise对象,
//用await直接获取 resolve传递出来的异步数据。
//而之前我们用then 才能拿到数据data。then(function(data){})
let film = await getfilm();
//必须等待await结束后才继续执行下面代码
console.log(film);
//相当于实现同步了
let sing = await getSing();
console.log(sing);
let hot = await getHotpot();
console.log(hot);
let tea = await getTea();
console.log(tea);
}
fn();
可以任意先做什么就做什么,先log谁就log谁
async function fn(){
let film = await getfilm();
let sing = await getSing();
let hot = await getHotpot();
let tea = await getTea();
console.log(sing);
console.log(tea);
console.log(hot);
console.log(film);
}
fn();
关于promise:
1、没有resolve、没有reject
不会调用then或者catch。
let p = new Promise(()=>{
//函数里面是同步代码
console.log('同步执行代码');
})
//只有resolve才会执行then
p.then(()=>{
console.log('then');
})
console.log('同步2');
输出 同步执行代码、同步2
2、resolve没有参数
没有参数也就是没有传数据
let p = new Promise((resolve)=>{
//函数里面是同步执行代码
console.log('同步执行代码');
resolve();//有then就会执行
})
//只有resolve才会执行then
p.then(()=>{
console.log('then微任务');
})
console.log('同步2');
注意then是异步的微任务,等待同步任务完成后,才执行微任务。
依次输出同步执行代码、同步2、then微任务。
3、resolve有参数
let p = new Promise((resolve)=>{
//函数里面是同步代码
console.log('同步执行代码');
resolve('参数data');
})
//只有resolve才会执行then
p.then((data)=>{
console.log('then微任务');
console.log(data);
})
console.log('同步2');
注意then是异步的微任务,等待同步任务完成后,才执行微任务。
依次输出同步执行代码、同步2、then微任务、参数data。
3、有resolve、reject。
resolve则执行then、reject则执行catch。且改变不可逆。
当isPass = true,调用resolve。
当为false,调用reject。
const isPass = true;
const p = new Promise((resolve,reject)=>{
if(isPass){
resolve("通过了")
}else{
reject("没有通过哦")
}
});
p.then(grade =>{
console.log(`你的四六级结果是,${
grade}`);
})
.catch(grade =>{
console.log(`你的四六级结果是,${
grade}`);
})
在promise对象p 加上finally,不管什么情况,都会调用
.finally(() =>{
console.log("不管怎么样那还是要吃大餐的");
});
关于async
1、async函数返回的是promise对象
async function fun1(){
return 20
}
//acync返回的是promise对象
console.log(fun1());
//fun1、fun2 函数是等价的
function fun2(){
return new Promise((resolve)=>{
resolve(20)
})
}
console.log(fun2());
2、和await配合在例子也提过了。
练习:
console.log('start1');
async function f1(){
await f2();//立即去执行f2函数
//awaitf2(); 的后面相当于 then
//将console.log('2');放入微任务队列
console.log('2');
}
async function f2(){
console.log('3');
}
f1();
setTimeout(function(){
console.log(4);
},500)
console.log(5);
setTimeout(function(){
console.log(6);
},0)
new Promise(resolve=>{
console.log(7);
resolve();
}).then(function(){
console.log(8);
})
console.log(9);
process.nextTick(()=>{
console.log('process.nextTick');
})
new Promise(resolve=>{
console.log(10);
resolve();
}).then(function(){
console.log(11);
})
console.log('end');
依次输出start1、3、5、7、9、10、end、process.nextTick、2、8、11、6、4。
总结:
1、同步
2、process.nextTick
3、异步(4、微任务:promise.then…。 5、宏任务:计时器、ajax,读取文件…)
补充:
promise链式调用
<script>
new Promise((resolve,reject)=>{
console.log(1);
resolve(100)
})
.then(v=>{
new Promise((resolve,reject)=>{
console.log(2+',v:'+v);
resolve(200)
}).then(v=>{
console.log(3+',v:'+v);
}).then(v=>{
console.log(4+',v:'+v);
return 300
}).then(v=>{
console.log(5+',v:'+v);
return 400
})
})
.then(v=>{
console.log(6+',v:'+v);
})
</script>
链式调用,then一定依赖同一个promise的上一个then中return的值。
结果:
第一个then中没有return给第二个then,而且第一个then中有promise,它是异步操作
加上return 后,执行完第一个then才到第二个then。
结果:
关于reutrn的值:必须是当前then的return 的promise的最后一个then一定要有return。
有return:
再怎么嵌套都要保证最后一个then有return。
绕啊绕
<script>
new Promise((resolve,reject)=>{
resolve(100)
})
.then(v=>{
return new Promise((resolve,reject)=>{
console.log(1+',v:'+v);
resolve(200)
}).then(v=>{
console.log(2+',v:'+v);
return 300
}).then(v=>{
console.log(3+',v:'+v);
return 3
}).then(v=>{
console.log(33+',v:'+v);
return 33
}).then(v=>{
console.log(333+',v:'+v);
return 333
}).then(v=>{
console.log(3333+',v:'+v);
return 400
})
})
.then(v=>{
return new Promise((resolve,reject)=>{
console.log(4+',v:'+v);
resolve(500)
}).then(v=>{
console.log(5+',v:'+v);
return 600
}).then(v=>{
console.log(6+',v:'+v);
return 6
}).then(v=>{
console.log(66+',v:'+v);
return 66
}).then(v=>{
console.log(666+',v:'+v);
return 666
}).then(v=>{
console.log(6666+',v:'+v);
return 700
})
})
.then(v=>{
return new Promise((resolve,reject)=>{
console.log(7+',v:'+v);
resolve(400)
}).then(v=>{
console.log(8+',v:'+v);
return 800
}).then(v=>{
console.log(9+',v:'+v);
return 9
}).then(v=>{
console.log(99+',v:'+v);
return 99
}).then(v=>{
console.log(999+',v:'+v);
return 999
}).then(v=>{
console.log(9999+',v:'+v);
return 1000
})
})
.then(v=>{
return new Promise((resolve,reject)=>{
console.log(10+',v:'+v);
resolve(1000)
}).then(v=>{
console.log(11+',v:'+v);
return 1200
})
})
.then(v=>{
console.log(12+',v:'+v);
})
</script>
结果很顺序
但是当其中有的没有return,而且还有promise对象时。
把第1个、第2个、第四个的return删掉后
<script>
new Promise((resolve,reject)=>{
resolve(100)
})
.then(v=>{
new Promise((resolve,reject)=>{
console.log(1+',v:'+v);
resolve(200)
}).then(v=>{
console.log(2+',v:'+v);
return 300
}).then(v=>{
console.log(3+',v:'+v);
return 3
}).then(v=>{
console.log(33+',v:'+v);
return 33
}).then(v=>{
console.log(333+',v:'+v);
return 333
}).then(v=>{
console.log(3333+',v:'+v);
return 400
})
})
.then(v=>{
new Promise((resolve,reject)=>{
console.log(4+',v:'+v);
resolve(500)
}).then(v=>{
console.log(5+',v:'+v);
return 600
}).then(v=>{
console.log(6+',v:'+v);
return 6
}).then(v=>{
console.log(66+',v:'+v);
return 66
}).then(v=>{
console.log(666+',v:'+v);
return 666
}).then(v=>{
console.log(6666+',v:'+v);
return 700
})
})
.then(v=>{
return new Promise((resolve,reject)=>{
console.log(7+',v:'+v);
resolve(400)
}).then(v=>{
console.log(8+',v:'+v);
return 800
}).then(v=>{
console.log(9+',v:'+v);
return 9
}).then(v=>{
console.log(99+',v:'+v);
return 99
}).then(v=>{
console.log(999+',v:'+v);
return 999
}).then(v=>{
console.log(9999+',v:'+v);
return 1000
})
})
.then(v=>{
new Promise((resolve,reject)=>{
console.log(10+',v:'+v);
resolve(1000)
}).then(v=>{
console.log(11+',v:'+v);
return 1200
})
})
.then(v=>{
console.log(12+',v:'+v);
})
</script>
结果有undefined,而且then中有promise异步,执行顺序不一致,不过then所依赖的同级上一个then的return的值不变。
再补充:
1、fulfilled状态的promise,自动向下找then,在then中返回非promise的值,它会生成状态fulfilled的新promise对象,传入下一个回调函数。
<script>
new Promise((resolve,reject)=>{
resolve(100)
}).then(v=>{
console.log(1+',v:'+v);
return 200
}).then(v=>{
console.log(2+',v:'+v);
}).catch(v=>{
console.log(3+',v:'+v);
})
</script>
2、
rejected状态的promise,自动向下找catch,在catch中返回非promise的值,它会生成状态fulfilled的新promise对象,传入下一个回调函数。
<script>
new Promise((resolve,reject)=>{
reject(100)
}).then(v=>{
console.log(1+',v:'+v);
return 200
}).catch(v=>{
console.log(3+',v:'+v);
return 300
}).then(v=>{
console.log(4+',v:'+v);
}).catch(v=>{
console.log(5+',v:'+v);
})
</script>
3、rejected状态的promise,自动向下找catch,在catch中返回promise对象的值,根据该promise对象的状态决定传入下一个回调函数。
<script>
new Promise((resolve,reject)=>{
reject(100)
}).then(v=>{
console.log(1+',v:'+v);
return new Promise.reject(200)
}).then(v=>{
console.log(2+',v:'+v);
}).catch(v=>{
console.log(3+',v:'+v);
return new Promise.reject(300)
}).then(v=>{
console.log(4+',v:'+v);
}).catch(v=>{
console.log(5+',v:'+v);
}).catch(v=>{
console.log(6+',v:'+v);
}).catch(v=>{
console.log(7+',v:'+v);
})
</script>
4、
fulfilled状态的promise,自动向下找then,在then中返回promise对象的值,根据该promise对象的状态决定传入下一个回调函数。
new Promise((resolve,reject)=>{
resolve(100)
}).then(v=>{
console.log(1+',v:'+v);
return new Promise.reject(200)
}).then(v=>{
console.log(2+',v:'+v);
}).catch(v=>{
console.log(3+',v:'+v);
}).then(v=>{
console.log(4+',v:'+v);
}).catch(v=>{
console.log(5+',v:'+v);
})
</script>
5、抛出错误异常
都会生成rejected状态的promise。
<script>
new Promise((resolve,reject)=>{
resolve(100)
}).then(v=>{
console.log(2+',v:'+v);
throw new Error('xxx')
}).catch(v=>{
console.log(3+',v:'+v);
throw new Error('xxx')
}).then(v=>{
console.log(4+',v:'+v.message);
}).catch(v=>{
console.log(5+',v:'+v.message);
}).catch(v=>{
console.log(6+',v:'+v.message);
})
</script>
边栏推荐
- 04-JS作用域及常用数据类型(对象、数组、字符串、数字、时间)
- js在字符串指定位置插入字符串
- 案例复现,带你分析Priority Blocking Queue比较器异常导致的NPE问题
- C-V2X八大误区澄清和发展辩思
- 1.servlet规范简单整理
- Web3 Entrepreneur's Guide: How to Build a Decentralized Community for Your Product?
- Shaanxi cas: 2055042-71-0N-(alkyne-tetraethylene glycol)-biotin price
- PlutoSDR学习指南【3】官方软件“IIO Oscilloscope”
- A043: These three abilities are indispensable for good chip design
- SH7001单电池恒压线性充电IC
猜你喜欢
A043: These three abilities are indispensable for good chip design
陕西cas:2055042-71-0N-(炔-四聚乙二醇)-生物素价格
案例复现,带你分析Priority Blocking Queue比较器异常导致的NPE问题
锂电池充电芯片IC
Web3 Entrepreneur's Guide: How to Build a Decentralized Community for Your Product?
NLP标注工具Brat的简单使用
04-JS作用域及常用数据类型(对象、数组、字符串、数字、时间)
ESI VA One 2021软件安装包和安装教程
【数字赛道命题三】基于复旦微FPGA平台实现H.264视频解码
EastWave应用:负折射现象实时演示
随机推荐
何为API服务网关
Five minutes to teach you intranet penetration
反射笔记2.0
class 继承的重点
PerfView专题 (第一篇):如何寻找热点函数
继承和多态的总结
FS2956A 输入8-120V 用于液晶仪表5V-USB 充电口方案
在华门店数超星巴克,瑞幸咖啡完成“逆袭”?
二叉树详解
Kubernetes应用发布思路分析
《公共管理学》重点总结-陈振明版
SQL Runtime SLX中的优化设计有哪些?
基于数据库实现通用异步缓存系统
Jmeter性能测试
从零开始Blazor Server(10)--编辑角色
SM5200原厂SOT23-6 500mA 线性锂电子替代芯片
编程手册管理软件-涉及各类编程语言
蚂蚁集团开源密码学基础库 BabaSSL 正式更名“铜锁”
开源H.264 Video Encoder IP Core V2.0 介绍
目标检测学习笔记——小目标检测