标签:自动 fun mat callback 难度 settime es6 增加 nbsp
一 什么时候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
标签:自动 fun mat callback 难度 settime es6 增加 nbsp
原文地址:https://www.cnblogs.com/junlebao/p/13198027.html