ES6中为原生JS新增加了一个对象用来解决异步编程和问题,这个对象就是Promise。
那promise究竟是什么呢?这个真的是一件很难解释清楚的事情,他一共有三种状态,就像是一个岔路口,不管你来或者不来,我都在这里,这时候的状态是初始状态,也就是pen
din
g
(进行时)。
当你走到分岔口的时候,只能向左(fulfilled:成功
)或者向右(rejected:失败
),而且没有回头的权利(promise的状态不可以改变)。当然,你也可能一辈子走不到那个岔路口。这里只是一个比喻。
我们先来看一下语法
var num;
var promise = new Promise(function(resolve,reject){
if (num){
resolve(num);
}else{
reject();
}
});
首先,new了一个Promise对象,传了一个函数,里面传了两个参数,第一个参数代表成功,第二个参数代表失败。
我在最上面定义了一个变量num,如果num的值为真的,就会选择resolve,如果失败了,就会选择reject。
但上面这些代码还不够,这些代码只是决定了promise的状态,并没有执行呢,我们先来复习一遍。
想要创建一个Promise对象,需要先new一下,然后传一个函数,函数的两个参数分别代表了promise的两种状态,如果特定的条件成立,promise的状态就会变成成功,否则状态就会变成失败。
现在,我们已经可以成功判断出了小p的状态,可是有了这些还不够,选择了哪条路之后要做的事情是什么呢?继续向前走啊!这时候,我么就要引入一个新的方法来帮助小p继续向前走了,这个方法就是then
then方法里面有两个参数,分别是小p上面两个参数的回调函数,如果小p的状态是成功,就会走then方法的第一个参数,如果小p的状态是失败,就会走tnen方法的第二个回调函数。只这样给大家说可能不是很好理解,我们再来看一个例子:
var num=1;
var promise = new Promise(function(resolve,reject){
if (num){
resolve(num);
}else{
reject();
}
});
promise.then(()=>console.log('成功'),()=>{console.log('失败')});
我们给then方法传了两个函数,如果小p的状态是成功,就会执行第一个函数,打印出成功,反之亦然。
我们先来判断一下小p的状态,如果num是真的,小p选择的路就是成功,如果num是假的,小p选择的路就是失败。
num的值为1,是真的,证明这时候小p选择的是成功的那条路,然后之后调用了then方法继续向前走,如果状态是成功就会执行第一个函数,反之亦然,那么打印出来的应该是成功,我们打开浏览器看一下猜想是否正确。
成功
浏览器打印出来了,证明我们刚刚的猜想没有错误。
现在我们已经能够正确的判断出小p的状态并且让他执行了,可是有的人觉得then里面传两个函数的写法太low了,把成功状态和失败状态的方法写在一起容易混淆,有没有逼格更高的一点写法?
当然有了。这个方法的名字是catch,专门用来放错误状态下执行的函数。先来看一下基本语法:
promise
.then(()=>console.log('成功'))
.catch(()=>{console.log('失败')});
呐~,这就是你们想要的逼格高的写法,其实和上面的没什么两样,只不过现在then里面只传了一个函数,就是成功状态下要执行的函数,那么失败状态下呢?就会直接执行catch里面的代码了。
还是回到最初的例子,我们的小p现在已经选择了一条路向前走了,人生的路途中难免有错误的决定,小p也是一样的,可是最难过的是我们做出错误的决定的时候,我们自己往往是不知晓的,这时候我们就需要一个明智的人来为我们指点一二,告诉我们什么是对,什么是错,让我们的人生少走弯路。小p人生,不对,码生的这位智者就是catch,在小p犯错误的时候及时制止,避免继续错误的走下去。
我们来看一下具体的代码
var num=1;
var promise = new
Promise(function(resolve,reject){
if (num){
console.log(a);
resolve(num);
}else{
reject();
}
});
promise.then(()=>console.log('成功')).catch(()=>console.log('失败'));
我们看上面的代码,虽然特定的条件成立,但仍然会走catch函数,提醒小p发生了错误,避免继续错下去。
如果我们人生也有一位这样的智者,应该会避免很多错误,可惜没有如果。
再来介绍几个方法,promise也算是入门了。
今天要介绍的第一个方法名字是finally(),基本语法和then和catch一样,我们来看一下:
let num=1;
let promise = new Promise((resolve,reject)=>{
if(num){
resolve();
}else{
reject();
}
});
promise.then(()=>console.log('成功')).catch(()=>console.log('失败')).finally(()=>console.log('我是最后执行的函数'))
我们先来分析一下,首先定义了一个num的值为1,又写了一个promise,之后如果promise的状态是成功,就会打印出 成功 ,如果状态是失败,就会打印出 失败。但我们定义的num值为1,所以此时promise的状态就是成功的,应该可以打印出 成功 ,但我在最后面又写了一个finaly的方法,里面的函数执行之后会打印出 我是最后执行的函数 。最后一个方法什么时候会执行,暂时还不知道,我们先打开浏览器看一下吧。
浏览器打印出了 成功 和 我是最后执行的函数
我们把num的值改为0再试一次
浏览器打印出了 失败 和 我是最后执行的函数
所以 finally函数不管小p的状态是成功或者失败,都会触发,就像你生命中该遇见的人,不管你有多优秀,或者多狼狈,他都在你做出决定之后,遇见你。
finally函数在小p的状态发生改变之后会执行的操作,不管状态是成功还是失败,都会执行此函数,就像你生命中躲不掉的那个人,遇到了就珍惜吧。
接下来,我们要介绍一个神奇的方法了,这个方法会颠覆你我对传统promise的认知,让你认识到,原来promise还可以这样玩,同时也是一个非常方便的方法。
平时我们写promise的时候一般会先new一下,就像这样
let promise = new Promise((resolve,reject)=>{
if(num){
resolve();
}else{
reject();
}
});
但现在有一种更加简单的方法了
let p1 = Peomise.resolve('');
我们打印一下p1看一下
打印出了一个promise实例,而且状态直接是成功,值为传进来的参数
什么 小p居然可以这样操作,对呀,我也是刚刚知道,小p居然可以这样玩。
这个方法可以直接把里面的参数转为promise实例,而且状态为成功。
就像是你辛辛苦苦的学习刷证书努力工作过上你想要的生活,有的人一出生就含着金钥匙出生,过着你努力了那么久的生活,人生本就是如此。
但是 说不定也有例外呢?
我们再来看几个例子
let promise = new Promise(res=>console.log('ddd'));
let p1 = Promise.resolve();
console.log('p1----',p1);
let p2 = Promise.resolve('ddd');
console.log('p2----',p2);
let p3 = Promise.resolve(promise);
console.log('p3----',p3);
我们看看不同的参数对这个神奇的方法有没有影响
打印结果如下
p1里面什么参数都没有传,打印出来的结果是一个成功状态的小p,
p2里面传了一个字符串,打印出来的结果也是一个成功状态下的小p,
p3里面传了一个我自己new的一个小p,结果打印出了一个初始状态下的小p。
我们来总结一下,如果Promise.resolve()里面的参数是一个不是promise实例,那么Promise.resolve就会返回一个成功状态下的promise实例,如果Promise.reslove传了一个promise实例,那么传入的是什么状态,返回的就是什么状态。
与Promise.resolve相反的一个方法叫做Promise.reject()方法,转入什么值打印出来的都是一个错误状态下的回调函数,但与Promise.resolve不同的是这个方法不管传入什么参数都会是失败状态下的promise实例,而且会立即抛出错误
我们来看几个例子
let promise = new Promise(res=>console.log('ddd'));
let p1 = Promise.reject('出错了');
console.log('p1----',p1);
let p2 = Promise.reject();
console.log('p2----',p2);
let p3 = Promise.reject(promise);
console.log('p3----',p3);
如果里面传的参数是字符串,就会返回一个失败状态下的promise实例,而且抛出错误,错误就是传的那个字符串
如果里面没有传递参数,就会返回一个失败状态相爱的promise实例,而且抛出的错误是一个undefined
如果里面传递的是一个promise实例,里面也是返回一个失败状态下的promise实例,抛出的错误是整个promise实例。
这真的是两个神奇的方法,直接让世间万物华丽的逆袭转身,具体是悲是喜,看造物者何用了。
如果一段代码里面有好多个promise实例,那么这样一个一个的调用是否有点麻烦,所以ES6为我们提供了两个可以同时控制多个promis实例的方法。
第一个方法如下
let pAll = Promise.all(['s','e','0']);
这个方法的参数是一个集合,里面的参数都是promise实例,如果不是promise实例的话,里面会自己调用Promise.resolve()方法转为promise实例,这个方法具体的作用是什么呢?
我们先来打印一下看看
里面的三个参数状态都是成功,所以这个大的promise实例的状态也是成功
那如果是别的情况呢?
let p = new Promise(resolve=>console.log('p'));
let pAll = Promise.all(['s','e','0',p]);
console.log(pAll);
只要有一个参数的状态是初始化,整个大的promise实例的状态就会成为初始化
如果有一个promise的状态是失败又会怎样呢?我们来看一下
var n = Promise.reject('失败了');
let pAll = Promise.all(['s','e','0',n]);
console.log(pAll);
浏览器运行的结果如下
只要集合中有一个的状态是失败,那么整个promise的状态就会成为失败,
总结来说,在Promise.all()这个方法参数的集合中,只有全部都是成功,状态才是成功,只要有一个状态是失败,那么整个promise的状态就是失败,如果有一个是初始化,那么状态就是初始化。当然,Promise.all的作用不止于此,今天只是给大家简单的介绍了一下,如果有兴趣的话可以后台私信我获取更加详细的笔记。
与Promise.all相对的方法有一个,就是Promise.race,同样是用来控制promise集合的一个大的promise实例,如果集合里面的参数不是promise实例,也会调用Promise.reslove来转为成功的promise实例。
他们的区别是Promise.race集合中只要有一个promise的实例发生改变,整个大的promise实例的状态就会跟着改变,最先改变的那个promise实例的返回值,就会传给大的promise实例
我们来看一个具体的例子
let pAll = Promise.race(['s','e','0']);
console.log(pAll);
传的三个参数都不是promise实例,所以会先调用Promise.resolve方法,都会转为成功的promise实例,所以大的promise状态就是成功
如果第一个参数的状态是失败会是什么呢?
var n = Promise.reject('失败了');
let pAll = Promise.race([n,'s','e','0']);
console.log(pAll);
如果第一个状态为失败,大的promise的状态就会变成失败,如果集合内的promise都是初始状态呢?
var n = new Promise(res=>console.log('c'));
var f = new Promise(res=>console.log('c'));
var c = new Promise(res=>console.log('c'));
let pAll = Promise.race([n,f,c]);
console.log(pAll);
如果三个状态是初始状态测不会有任何改变,只要有一个promise的状态发生了改变,大的promise的状态就会立刻改变
关于promise的知识点目前就说这么多吧,如果后台私信想了解更多的话会考虑后期更新的