Promise是什么?
Promise是异步编程的一种解决方案,比传统的解决方案--回调函数和事件--更加合理和强大。最早是在社区提出和实现,ES6将其写进了语言标准,统一了语法,原生提供了Promise对象。
好吧,那Promise到底是什么?嗯。。。。貌似可以提升逼格¥0#¥@
还是少一点套路直接上例子比较好理解。在敞开心扉之前,先请客官大人记住Promise的2大特性,①Promise的对象状态不受外界影响。②一旦状态改变,就不会再变,任何时候都可以得到这个结果。(试想你的代码中有这么个对你忠贞的姑娘,484灰常激动。)当然,Promise也有一些小缺憾,后文会提到。
场景1:
$.ajax({
****
success:dosomething(data){}
})
这是个最简单的AJAX异步获取数据的场景,一切都显得那么和谐完美无瑕,简直666,
好了,老板说我们的业务变得复杂了
场景2:
$.ajax({
****
success:fn(data){
$ajax({
***
success:dosomethis(data){
...
}
})
}
)}
这个场景描述描述的是一个AJAX请求依赖于另一个AJAX请求成功后获得的返回值,我们写出了两层嵌套的AJAX连环炮,你似乎已经能看到你的未来了,随着我们的业务变的越来越复杂,你的代码可读性会变的越来越差,你的连环炮越打越长,到后面你自己也找不到中间到底哪里会出错,会出什么错。这显然不够优雅~
场景2会轻松形成一个叫回调地狱的场景,可以让你的代码维护者花上一整天来弄懂你的这一些列连环炮到底是做什么的。这似乎是个报仇的好办法。好了,这并不好,作为一名优雅的不行的前端开发工程师,是时候来一波无形装逼了。
Promise基本用法
var promise = new Promise(function(resolve,reject){
// ... some code if(/* 异步操作成功 */){
resolve(value);
}else{
reject(error);}
});
Prominse构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject。他们是两个函数,由JavaScript引擎提供,不用自己部署。(通俗点讲就是。一个带了两个奇怪的函数作为参数的函数把你的异步代码包裹起来了作为参数给了Promise构造器造了一个Promise实例。优雅么,酸爽么,%……%¥)
那函数里面是什么鬼,回顾刚刚让你特别记住的两点的。就是每个Promise对象都有一个保存保存状态的功能,当Promise实例被创建出来的时候,她有了第一个状态Pending,然后被你包裹的那段异步代码开始执行,&……¥¥#*,如果一切ok,异步操作成功了,执行埋伏已久的resolve函数,并且把需要处理的返回值作为参数传递出去,Promise对象的状态从Pending置成Resolved(又称Fulfilled),要是其中发生了什么乱七八糟牛鬼蛇神的事情导致的异步操作失败了,执行reject函数并将错误信息传递出去,Promise对象的状态就会从Pending置成Rejected,你还需要记住刚刚的第二点,这个状态的改变不可逆且不可重复改变。这就是Promise承若的名字由来吧,多么美丽美好,仿佛看见十八岁的妹子在对你Promise Promise P...。
Promise实例生成以后,可以用then的方法指定Resolved状态和Reject状态的回调函数。先看写法
promise.then(function(value){
// success
},function(error){
// failure
});
then方法可以接收两个回调函数作为参数,第一个回调函数是Promise对象的状态变成Resolved时的回调,第二个则是Promise对象的状态变为Rejected时调用。第二个参数是可选的,这两个函数都自动接收Promise对象传出的值作为参数。
说了这么多,我们来看看如何改下我们之前的场景2
首先我们把异步操作都交给Promise去实例一个Promise对象,并且封装到一个方法作为返回值以供链式调用。
function doFir (){
return new Promise((resolve,reject)=>{
$.ajax({
****
success:resolve(value) //成功后改变Promise的状态并且将value交给resolve传递出去
error:reject(err) //失败后 将Promise状态Rejected并且将err交给reject传递出去
})
}) //整个Promise实例作为返回值返回出去
}
function doSec(value){
return new Promise((resolve,reject)=>{
$.ajax({
****
success:resolve(value) //成功后改变Promise的状态并且将value交给resolve传递出去
error:reject(err) //失败后 将Promise状态Rejected并且将err交给reject传递出去
})
}) //整个Promise实例作为返回值返回出去
}
function doThi(value){
return new Promise((resolve,reject)=>{
$.ajax({
****
success:resolve(value) //成功后改变Promise的状态并且将value交给resolve传递出去
error:reject(err) //失败后 将Promise状态Rejected并且将err交给reject传递出去
})
}) //整个Promise实例作为返回值返回出去
}
为了体现Promise的优雅,多加了一个异步操作,注意现在三个任务函数的关系是并列的,他们共享同一个作用域,在作用域链中的位置也是同级的,作用域链不理解的同学跳过没关系。然后开始展现Promise的优雅。bi~~~u~~
doFir().then((value) => {doSec(value)})
.then((value) => {doThi(value)})
QAQ!~~~好吧我们稍微拆解一下说明其中的那些优雅
doFir()
.then((value) => {doSec(value)})//这里then省略了第二个参数,也就是Promise为Rejected时候的回调,第一个 //回调函数会接收到success:resolve(value)传递出来的value参数,开始执行 //doSec()
.then((value) => {doThi(value)})//因为doSec()返回的是一个新的Promise对象,一样的你可以接着then
至此,一个嵌套的多层级的异步代码块通过使用Promise扁平化了,阅读者和编程者都能快速清晰的知道这一串链式调用到底要做什么。
好吧 优雅的和大家说88~