初识Promise
什么是promise?MDN官方文档的解释如下:
Promise 对象用于一个异步操作的最终完成(或失败)及其结果值的表示。简单点说,就是处理异步请求,我们经常会做些承诺,如果我赢了我就做A事情,如果输了我就做B事情。
这就是promise的中文含义:诺言,一个成功,一个失败。
那Promise在js中到底是个什么东西呢?看以下代码,可在浏览器中将其打印出来,如图:
通过prototype可以看出promise是一个构造函数。咱们先new一个promise看看能执行什么,代码如下:
new Promise(function(resolve,reject){
console.log("1")
})
这段代码直接打印出了1,在这段代码中,Promise的参数是一个函数,这个函数有两个参数,resolve,reject,按照官方文档的说法,Promise 对象用于表示一个异步操作的最终完成(或失败)及其结果的值。
什么意思呢?就是promise这个值刚一定义出来,并不知道代码会是完成状态或是失败状态,所以Promise存在了三种状态:
-
pedding状态,这个状态不是成功也不是失败;
-
fullfiled状态,就是成功状态,想要达到这个状态需要调用resolve方法;
-
rejected状态,想要达到这个状态需要调用reject方法;
其中,状态只能由pedding变换为rejected或者fulldied,不可逆转。
转换图如下:
将上面的代码放在浏览器里面,就会直接执行,打印出1,所以我需要将它用一个函数包裹一下:
var p = new Promise(function(resolve,reject){
console.log("1")
});
这样只需要在使用Promise时,调用这个函数就可以了。有人可能会问这有什么用,我直接实行console.log(1)不就行了,干嘛要包在Promise里面呢,什么鬼?这个需要回到Promise的作用上面来。
Promise的作用是什么?通俗的讲就是控制异步函数的调用。
上面的代码还不足以看出Promise的威力,只是告诉大家如何将Promise放到一个函数里面。
接着咱们按照文章开头举的是否嫁给我的例子来看一段代码:
function WeddingOrNot(){
return new Promise(function(resolve, reject){
setTimeout(function(){
if(Math.random()-0.5>0){
resolve('你要嫁给我,咱们下一步去领证');
}else{
reject('你不会嫁给我,后面的不需要执行了,咱们到此结束,')
}
}, 2000);
});
}
WeddingOrNot().then(function(data){
console.log(data);
}).then(function(){
console.log("买喜糖")
}).then(function(){
console.log("发请柬")
}).then(function(){
console.log('幸福的生活在一起')
}).catch(function(data){
console.log(data);
console.log('直接执行catch,所有的then都不会执行')
})
weddingornot是否结婚,是一个异步函数。是否结婚存在一个概率问题,这里用Math.random来计算:
-
如果嫁给我,将结果传递给resolve,将Promise由pedding状态变换为fullfiled状态,后面紧跟的then方法中的function会得到传递出过来的数据,并且then链调用会同步一个一个逐步执行;
-
如果不结婚,将结果传递给reject,后面的then一个都不会执行,直接跳到catch里面来执行。
分别看下执行结果如图:
或者
有兴趣的朋友可以自己测试一下。
假如结婚后中间出了一些状况离婚了,也需要直接跳到catch里面来,那要怎么实现呢,看代码:
function WeddingOrNot(){
return new Promise(function(resolve, reject){
setTimeout(function(){
if(Math.random()-0.5>0){
resolve('你要嫁给我,咱们下一步去领证');
}else{
reject('你不会嫁给我,后面的不需要执行了,咱们到此结束,')
}
}, 2000);
});
}
WeddingOrNot().then(function(data){
console.log(data);
}).then(function(){
console.log("买喜糖")
}).then(function(){
console.log("发请柬")
}).then(function(){
return new Promise(function(resolve,reject){
if(Math.random()-0.5>0){
console.log("经历了诱惑,没有出轨,继续在一起")
resolve('经历了诱惑,没有出轨,继续在一起');
}else{
reject("有人出轨,婚姻到此结束了,直接执行catch")
}
})
}).then(function(){
console.log('幸福的生活在一起')
}).catch(function(data){
console.log(data);
console.log('直接执行catch,所有的then都不会执行')
})
读代码,在发请柬和幸福的生活在一起之间咱们插入了一个then,里面的函数呢返回了一个Promise实例,并且这个实例会变为rejected或者fullfiled状态,并将结果传递出去。看下运行结果:
或者
可以看出,在then链的调用中,某个then返回另外一个promise实例,且也是按照随机数来变换promise的状态的。如果调动了reject,幸福生活在一起也不会执行,那这有是没用呢,刚才的判断出轨是同步执行的将其替换为异步执行测试一下,代码如下:
function WeddingOrNot(){
return new Promise(function(resolve, reject){
setTimeout(function(){
if(Math.random()-0.5>0){
resolve('你要嫁给我,咱们下一步去领证');
}else{
reject('你不会嫁给我,后面的不需要执行了,咱们到此结束,')
}
}, 2000);
});
}
WeddingOrNot().then(function(data){
console.log(data);
}).then(function(){
console.log("买喜糖")
}).then(function(){
console.log("发请柬")
}).then(function(){
return new Promise(function(resolve,reject){
setTimeout(function(){
if(Math.random()-0.3>0){
console.log('经历了诱惑,没有出轨,继续在一起')
resolve('经历了诱惑,没有出轨,继续在一起');
}else{
reject("有人出轨,婚姻到此结束了,直接执行catch")
}
},1000)
})
}).then(function(){
console.log('幸福的生活在一起')
}).catch(function(data){
console.log(data);
console.log('直接执行catch,所有的then都不会执行')
})
来看执行结果:
或者
或者
代码照样会按照你设计的then链逐步调用——这就是promise的威力。
关于结婚不结婚这个案例,如果不用promise实现会是什么样呢,看代码:
function xingfu(){
console.log("幸福的生活在一起")
}
function lihun(){
console.log("离婚了")
}
setTimeout(function(){
if (Math.random()-0.5>0) {
console.log("结婚继续往下走");
console.log("买喜糖")
console.log("发请柬");
setTimeout(function(){
if (Math.random()-0.3>0) {
console.log("经历了诱惑继续在一起")
xingfu();
} else {
console.log('有人出轨了,结束了')
lihun()
}
},300)
} else {
lihun()
}
},300)
运行结果大家自己去测试,这里就不贴图了。
可以看到,这段代码的组织结构产生了回调嵌套,组织代码顺序完全不如用promise实现看着顺眼。当然有的朋友会说:一个两个嵌套而已,还好。
那如果嵌套三个,四个,五个......想象一下。
promise还有一些很有意思的用法,不是一篇文章能讲完的,咱们下次继续。