Promise 是异步编程的一种解决方案,其实是一个构造函数,自己身上有all、reject、resolve这几个方法,原型上有then、catch等方法。(ps:关于原型:JavaScript高级 构造函数与原型篇)
Promise对象有以下两个特点。
(1)对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是Promise这个名字的由来,它的英语意思就是“承诺”,表示其他手段无法改变。
(2)一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved(已定型)。如果改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。
Promise功能:避免了回调地狱,把异步代码改成调用起来像同步代码。
// 语法:
// Promise————
// var p = new Promis(回调函数)
// 回调函数也有两个参数
// resolve ---------坚定
// reject-----------拒绝
var p = new Promise((resolve,reject)=>{
//默认状态——————pending
// 调用函数----resolve();
// 得到
// 成功状态————fulfilled
// 调用函数——--reject()
// 失败状态————rejected
// resolve();
reject();
})
console.log(p);
// 特点:1、转态不受外部影响
// 2、状态一旦发生改变,将不再变化
Promise的基本用法:
// 默认pending: 初始状态
var p=new Promise(function (resolve,reject) {
if("操作成功"){
resolve();//pending-->fulfilled 异步操作成功的回调函数
}else{
reject(); //pending-->reject 异步操作失败的回调函数
}
})
p.then(data => {//在外面调用then处理成功的逻辑
console.log("处理成功的逻辑");//fulfilled
}).catch(err=>{//在外面调用catch处理失败的逻辑
console.log("失败的逻辑");//reject
})
// then方法会在异步成功后调用,catch方法会在异步失败后调用
如果需要连续调用,就要用return
比如:
p1.then(data1 => {
console.log(data1);
return p2
}).then(data2 => {
console.log(data2);
return p3
}).then(data3 => {
console.log(data3);
})
接收一个Promise实例对象组成的数组,[p1,p2,p3]
只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数。
只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
reject("失败");
}, 3000);
});
const p2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("成功2");
}, 2000);
});
const p3 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("成功3");
}, 1000);
});
// 全部成功返回成功,有一个失败返回失败
let p = Promise.all([p1, p2, p3]).then((res) => console.log(res)).catch(err=>console.log(err));
接收一个Promise实例对象组成的数组,[p1,p2,p3]
返回是一个promise,then回调函数中得到每一个promise的详细结果,无论该promise是成功还是失败
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
reject('ok1')
}, 3000)
})
const p2 = new Promise((resolve, reject) => {
setTimeout(() => {
//resolve('ok2')
//reject('出错啦')
}, 1000)
})
const p3 = new Promise((resolve, reject) => {
setTimeout(() => {
reject('ok3')
}, 1000)
})
Promise.allSettled([p1, p2, p3]).then((res) => {
console.log(res)
}).catch((err) => {
console.log(err)
})
接收一个Promise实例对象组成的数组,[p1,p2,p3]
只要有一个成功的promise对象,就返回这个成功的Promise
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
reject('ok1')
}, 3000)
})
const p2 = new Promise((resolve, reject) => {
setTimeout(() => {
//resolve('ok2')
//reject('出错啦')
}, 1000)
})
const p3 = new Promise((resolve, reject) => {
setTimeout(() => {
reject('ok3')
}, 1000)
})
Promise.any([p1, p2, p3])
.then((res) => {
console.log(res)
})
.catch((err) => {
console.log(err)
})
all是等所有的异步操作都执行完了再执行then方法,那么race方法就是相反的,谁先执行完成就先执行回调。先执行完的不管是进行了race的成功回调还是失败回调,其余的将不会再进入race的任何回调
function promiseClick1(){
let p = new Promise(function(resolve, reject){
setTimeout(function(){
var num = Math.ceil(Math.random()*20); //生成1-10的随机数
console.log('2s随机数生成的值:',num)
if(num<=10){
resolve(num);
}
else{
reject('2s数字太于10了即将执行失败回调');
}
}, 2000);
})
return p
}
function promiseClick2(){
let p = new Promise(function(resolve, reject){
setTimeout(function(){
var num = Math.ceil(Math.random()*20); //生成1-10的随机数
console.log('3s随机数生成的值:',num)
if(num<=10){
resolve(num);
}
else{
reject('3s数字太于10了即将执行失败回调');
}
}, 3000);
})
return p
}
function promiseClick3(){
let p = new Promise(function(resolve, reject){
setTimeout(function(){
var num = Math.ceil(Math.random()*20); //生成1-10的随机数
console.log('4s随机数生成的值:',num)
if(num<=10){
resolve(num);
}
else{
reject('4s数字太于10了即将执行失败回调');
}
}, 4000);
})
return p
}
Promise
.race([promiseClick3(), promiseClick2(), promiseClick1()])
.then(function(results){
console.log('成功',results);
},function(reason){
console.log('失败',reason);
});
与Promise对象方法then方法并行的一个方法就是catch,与try catch类似,catch就是用来捕获异常的,也就是和then方法中接受的第二参数rejected的回调是一样的,如下:
function promiseClick(){
let p = new Promise(function(resolve, reject){
setTimeout(function(){
var num = Math.ceil(Math.random()*20); //生成1-10的随机数
console.log('随机数生成的值:',num)
if(num<=10){
resolve(num);
}
else{
reject('数字太于10了即将执行失败回调');
}
}, 2000);
})
return p
}
promiseClick().then(
function(data){
console.log('resolved成功回调');
console.log('成功回调接受的值:',data);
}
)
.catch(function(reason, data){
console.log('catch到rejected失败回调');
console.log('catch失败执行回调抛出失败原因:',reason);
});
resolve返回一个成功的promise
reject返回一个失败的promise
function promiseClick(){
let p = new Promise(function(resolve, reject){
setTimeout(function(){
var num = Math.ceil(Math.random()*20); //生成1-10的随机数
console.log('随机数生成的值:',num)
if(num<=10){
resolve(num);
}
else{
reject('数字太于10了即将执行失败回调');
}
}, 2000);
})
return p
}
promiseClick().then(
function(data){
console.log('resolved成功回调');
console.log('成功回调接受的值:',data);
},
function(reason){
console.log('rejected失败回调');
console.log('失败执行回调抛出失败原因:',reason);
}
);