ES6 promise用法总结
一 什么时候promise?
promise是异步编程的一个解决方案,是一个构造函数,身上带着all,resolve,reject,原型上有cath,then等方法
promise有两个特点:
1) 对象的结果不受外界影响,promise对象就代表一个异步操作,它有三种状态:pedding(进行中) fulfiled(已完成) rejected(已失败),只有异步操作的结果能够改变状态,其它任何操作都无法改变这个状态
2) 一旦状态改变,任何时候都会得到结果,而且不能够再改变这中状态. 状态的改变只有两种可能:pedding----->rulfiled pedding--->rejected 只要这两种状态发生了,转态就凝固了,这时称resolved(已定型)
下面我们简单new promise一下
let result= new Promise((resolve,reject)=>{
setTimeout(() => {
console.log("执行成功"); resolve("需要返回的数据接口")
}, 2000);
})
我们用打开页面,去控制台查看
执行过程: 执行一个异步操作,也就是settimeout,2s后打印执行成功,然后回调resolve方法
我们new promise对象的时候,自动执行了里面的内容,我们没有办法控制promise什么时候执行,
所以我们通常在使用它的时候在它的外面套一个函数,当我们需要用到它的时候去执行函数就可以了
<body>
<button onclick="btnClick()">执行操作</button>
</body>
<script>
function btnClick(){
let result = new Promise((resolve, reject) => {
setTimeout(() => {
console.log("执行成功"); resolve("需要返回的数据接口")
}, 2000);
})
return result
}
点击按钮,控制台结果输出:执行成功
放在函数中,我们返回的promise对象,对象身上有then,catch,all等方法了
上面的代码中还有resolve,它是什么呢 下面我们还是代码展示
btnClick().then((data)=>{
console.log(data);
})
调用promise对象(也就是btnClick()的返回值)的then方法,then方法里面的参数是一个函数,该函数的参数接受resolve里面的返回值,这时就会输出:
这样一来,你应该就知道了原来then在btnClick执行异步操作完毕之后被执行,这就是promise的作用了.
promise只是能够简化层层调用的写法,而实质上最主要的精髓在于用维护转态,处理状态使得调用及时,相比于callback来说更加简单,灵活.
backcall方式
asyncFunc1(opt, (...args1) => {
asyncFunc2(opt, (...args2) => {
asyncFunc3(opt, (...args3) => {
asyncFunc4(opt, (...args4) => {
// some operation
})
})
})
})
可以看到,我们没增加一个异步请求,就会多添加一层回调函数的嵌套,这段代码中四个异步函数的嵌套已经开始使一段本可以语言明确的代码编程不易阅读与维护了
promise方式
new proimse((resolve,reject)=>{ ansyncFunc1(opt,(...arg1)=>{ resolve(result1)
}) }).then((data1)=>{ return asyncFunc2(opt,(...args2)) }).then((data2)=>{ return asyncFunc3(opt,(...args2)) }).then((data3)=>{
return asyncFunc3(opt,(...args2)) }).then((data4)=>{ some operation })
两者比较,虽然看起来,promise方式虽然看起来代码量庞大了,但是缺更容易理解了,而callback嵌套,使人看到特别头疼,而且会加大维护的难度.这就是promise优势所在.
reject用法
上面介绍了resove成功的时候的回调,就是讲promise的状态从pedding--->fulfiled的转态.而reject就是讲promise的状态从pedding--->rejected状态,这样我们就可以在then方法中捕获调用失败的信息
function btnClick(){
let result = new Promise((resolve, reject) => {
setTimeout(() => {
var flag = false
if(flag){
resolve("成功拿到flag")
}else{
reject("没有拿到flag")
}
}, 2000);
})
return result
}
btnClick().then((data)=>{
console.log("接收resolve的数据--->"+data);
},(err)=>{
console.log("接收reject的回调--->"+err);
})
控制台打印
promise调用then方法时,往里面传了两个参数,第一个是接收resolve的函数,第二个是接收reject调用失败的函数
因为我们将flag设置的为false则执行reject然后then方法中捕获到调用失败的信息,并打印
catch的用法
与Promise对象方法then方法中第二个回调函数相同的一个方法就是catch,catch也是是用来捕获异常的.与then中的用法是一样的,
下面介绍一下它的强大之处
function btnClick(){
let result = new Promise((resolve, reject) => {
setTimeout(() => {
var flag = true
if(flag){
resolve("成功拿到flag")
}else{
reject("没有拿到flag")
}
}, 2000);
})
return result
}
btnClick().then((data)=>{
console.log("接收resolve的数据--->"+nodata);
}).catch((err)=>{
console.log("接收reject的回调--->" +err);
})
控制台没有报错而是将报错的信息传给了catch,然后进行输出打印
这样的话,即使进入了resove的then方法中,有错误,也不会报错了
all的用法
all是与then同级的另一个方法,all方法,该方法提供了并行执行异步操作的能力,并且在所有异步操作执行完后并且执行结果都是成功的时候才执行回调。
function btn1(){
let result1 = new Promise((reslove,reject)=>{
setTimeout(()=>{
let num = parseInt(Math.random() * 20 + 1)
console.log("获得第一个数据");
reslove(num)
},1000)
})
return result1
}
function btn2(){
let result2 = new Promise((reslove, reject) => {
setTimeout(() => {
let num = parseInt(Math.random() * 20 + 1)
console.log("获得第二个数据");
reslove(num)
}, 2000);
})
return result2
}
function btn3() {
let result3 = new Promise((reslove, reject) => {
setTimeout(() => {
let num = parseInt(Math.random() * 20 + 1)
console.log("获得第三个数据");
reslove(num)
}, 3000);
})
return result3
}
Promise.all([btn1(),btn2(),btn3()]).then((result)=>{
console.log("获得全部数据,可以渲染页面");
console.log(result);
})
promise.all中的参数是一个promise对象的数组,然后执行,当他们全部执行完毕后,会生成一个数组,里面就是全部的数据.
分别执行得到结果,all统一执行完三个函数并将值存在一个数组里面返回给then进行回调输出,结果如下
all方法,通常是用在一个页面需要加载数据需要同时拥有才能去渲染的情况,例如上边的例子,需要获得三个数据,然后才可以渲染页面
race方法
all方法是全部执行完毕之后才返回结果,而race方法是最先执行完毕的可以进入race的回调,其余的就不能再进入了
function btn1() {
let result1 = new Promise((resolve, reject) => {
setTimeout(() => {
let num = parseInt(Math.random() * 20 + 1)
if(num>10){
console.log("4s获得第一个数据即将执行resolve");
resolve(num)
}else{
console.log("4s执行函数失败,即将执行reject");
reject("获取失败")
}
}, 4000)
})
return result1
}
function btn2() {
let result2 = new Promise((resolve, reject) => {
setTimeout(() => {
let num = parseInt(Math.random() * 20 + 1)
if(num>10){
console.log("2s获得第二个数据,即将执行resolve");
resolve(num)
}else{
console.log("2s执行函数失败,即将执行reject");
reject("获取失败")
}
}, 2000);
})
return result2
}
function btn3() {
let result3 = new Promise((resolve, reject) => {
setTimeout(() => {
let num = parseInt(Math.random() * 20 + 1)
if(num>10){
console.log("3s获得第三个数据,即将执行resolve");
resolve(num)
}else{
console.log("3s执行函数失败,即将执行reject");
reject("获取失败")
}
}, 3000);
})
return result3
}
Promise.race([btn1(), btn2(), btn3()]).then((result)=>{
console.log("获得数据:"+result);
console.log("回调完成");
}).catch((err)=>{
console.log(err);
})
控制台输出,第一个回调失败时,下面的不会再进入race回调
控制台输出,第一个回调成功时,下面的也不会再进入race回调
综上所述,就是用race方法时,先执行完的无论是resolve还是reject都将会进入race回调,并且后面的不会再进入回调.
race方法,应用场景:代码如下
function btn1(){
let result = new Promise((resolve,reject)=>{
//异步请求,比ajax,axios等
resolve(data)
})
return result
}
function time(){
let result = new Promise((resolve,reject)=>{
setTimeout(() => {
reject("请求超时")
}, 10000);
})
return result
}
Promise.race([btn1(),time()]).then((data)=>{
console.log(data);
}).catch((err)=>{
console.log(err);
})
time()为一个异步操作10s的时间,让btn1()和它同时奔跑,如果btn1()在10s内获得数据,则显示数据,否则显示请求超时
这个就是看大佬们的博客,自己的一点理解,然后有不对的地方可以提出来,共同进步,讨论,学习,
下面时大佬博客的链接:https://blog.csdn.net/qq_34645412/article/details/81170576
最新文章
- CSharpGL(19)用glReadPixels把渲染的内容保存为PNG图片(C#)
- SVN服务器和客户端安装教程
- Java 2D API - 2. Graphics 入门
- 2016某知名互联网公司PHP面试题及答案
- Bootstrap系列 -- 26. 下拉菜单标题
- NSInvocation的使用(转)
- makefile for VCS from Syn@psys
- Js把URL中的参数解析为一个对象
- 二、nginx搭建图片服务器
- MySQL的char和varchar针对空格的处理
- LeetCode编程训练 - 合并查找(Union Find)
- Python Django CBV下的通用视图函数
- html-字体属性
- python基础(2)-运算符&;while循环
- /proc文件系统(二):/proc/<;pid>;/stat
- sql语句之from子句
- ArcGIS URL 组成
- VCSA 6.5 升级 VCSA 6.7
- My personal website:http://47.94.240.229:8080/yjh/project/
- LongAdder &; AtomicInteger
热门文章
- 小谢第10问:前端JS下载文件、表格
- Keycloak快速上手指南,只需10分钟即可接入Spring Boot/Vue前后端分离应用实现SSO单点登录
- 当微信小程序遇到云开发,再加上一个类似 ColorUI 的模板,人人都能做小程序了
- Rocket - diplomacy - NodeImp
- Redis 入门到分布式 (三) Redis客户端的使用
- 从零搭建Window前端开发环境
- Android中Widget开发步骤
- SpringBoot 2.3 整合最新版 ShardingJdbc + Druid + MyBatis
- @codeforces - 575E@ Spectator Riots
- 设计模式系列之工厂模式三兄弟(Factory Pattern)