1.promise是什么?
promise是ES6的一个方案,语法上讲是一个对象,针对异步的操作,用来解决避免掉入回调地狱的问题
- 首先我们来了解游览器的处理机制
也就是入栈和出栈,我们的代码中有事情需要处理,将这个事情放到游览器的内部去运行,我们把它比作一个邮箱,把手上还未处理的事情比作一个邮件,我们把邮件一封一封放进邮箱,等待邮件被寄出,但是邮箱一次性只能拿出一封邮件去执行,这个过程我们把它称为出栈,并且永远只拿最上层的邮件,因为代码是从上到下运行的,当一封邮件出栈被执行完,这个时候邮递员的手上没有事情做,它就会再从邮箱中拿出一封,那么下面的三个状态就好理解了
ES6将程序分为3中转台
- pending:挂起(等待),处于未决阶段,表示事情还在挂起中,最终结果没有出现
- resolved:已处理,处于已决决断,表示已决出现结果,并且可以按照正常的逻辑进行下去
- rejected:已拒绝,也是已处理的一种,已决阶段,但无法按照正常的逻辑进行下去,就好比上面我提到的邮件,被邮递员拿出来之后,因为种种原因没有被寄出,有可能是没有填写邮编地址,或者地址错误,也可能是半路被弄丢了,反正就是被拒绝处理了
以上无论是状态还是阶段,都是不可逆的,也就是说邮递员只会取件,不会把邮件放回去
resolved 是一个正常的已决阶段下的状态,后续处理为thenable
rejected 是一个非正常的已决阶段下的状态,后续处理为catchable
2.说了这么多,基本的promise运行已经大概了解,我们上代码
// 创建一个变量接收这个对象
const pro = new Promise((resolve,reject)=>{
// 未决阶段
// 通过调用resolve函数将promise推向已决阶段中的resolved状态
//
// resolve和reject只能写一个,如果使用多个则只有第一个有效
// 传递参数只能有一个,可以是任意数据类型的,表示推向状态的数据
reject(123)
// resolve({})
})
// console.log(pro)
pro.then(data=>{
// then()方法,已处理后再执行接下来的事情,也就是队列
console.log(data)
},err=>{
// 失败后返回的内容
console.log(err)
})
我们也可以new一个新的promise方法
const pro1 = new Promise((resolve,reject)=>{
resolve(1)
})
const pro2 = new Promise((resolve,reject)=>{
resolve(2)
})
// Pro2的队列执行
pro2.then(data=>{
console.log(data)
},err=>{
console.log(err)
})
有一点需要注意的是
resolve()括号里面可以随便写什么,但一定要写,否则不能代表进入了resolve()状态,也就不会执行下面的then()事件
接下来我们看一个实例:
// 我们需要按顺序显示红绿黄三种颜色,但执行的时间点都不同
//所以也不能时间短的先执行,必须按我们需要的顺序
function red(){
console.log('red');
}
function green(){
console.log('green');
}
function yellow(){
console.log('yellow');
}
var light = function(timmer, cb){
return new Promise(function(resolve, reject) {
setTimeout(function() {
cb(); //定时器里面执行方法的形参
resolve(); //表示进入已决状态,可以试一试不要这个resolve,看它会不会接着往下执行
}, timmer);
});
};
var step = function() {
Promise.resolve().then(function(){
return light(3000, red);
}).then(function(){
return light(2000, green);
}).then(function(){
return light(1000, yellow);
}).then(function(){
step(); //调用一次自己,进入循环播放
});
}
这里没有写已拒绝或已失败的阶段函数,因为没有后台数据请求,所以不需要
3.all(arr)方法
这个方法会返回一个新的Promise对象,里面所有的promise对象都成功了才会触发,一旦有一个失败,则该promise失败
下面我们来写一个会失败的
const proms = [];
for(let i = 0;i<10;i++){
proms.push(new Promise((resolve,reject)=>{
setTimeout(()=>{
if(Math.random() < 0.5){
console.log(i,"成功")
resolve(i)
}else{
console.log(i,"失败")
reject(i)
}
},getRandom(1000,3000))
}))
}
// 这里用all()方法
const pro = Promise.all(proms)
pro.then(data=>{
console.log("全部成功",data)
},err=>{
console.log("有失败",err)
})
得出的结果就是:
可以看到,有一个失败后,后面的表失败函数就不会再触发了
那么我们把数值直接调到1,看看全部成功的结果:
4.race(arr)方法
这个方法和上面的all()方法类似,返回一个全新的promise对象,当数组中任意一个promise对象完成时,就马上回去使用完成好的promise对象的结果,不管后面是否失败
还是刚才同样的例子,我们把all改成race
const pro = Promise.race(proms)
得出的结果便是:
可以看到,只要成功一个,它就会执行then()方法里面的函数
好了,关于promise的讲解就到这里