特点
1.对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:Pending(进行中)、Resolved(已完成)和Rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是Promise这个名字的由来,它的英语意思就是“承诺”,表示其他手段无法改变;
2.一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从Pending变为Resolved;从Pending变为Rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果。就算改变已经发生了,你再对Promise对象田静回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的;
Promise是什么
对于一个对象,我们如果想要了解,可以直接将其打印出来,通过console.log(Promise)将其打印出来,结果如下
通过上面的方法,我们可以知道promise是一个构造函数,有属于自己私有的all,reject,resolve,rece等方法,也有供实例化对象调用的方法,比如:catch,then等;
使用方法
// Promise里面传入函数类型的参数,这个函数类型的参数接收两个参数resolve reject
var tempP=new Promise(function(resolve,reject){
// 异步操作
setTimeout(function(){
console.log('icessun'); // 一秒之后打印出icessun
resolve('执行了'); // resolve是成功后的回调函数 里面的“执行了”是传入的参数
},1000)
});
// 那么tempP是一个实例对象,可以使用then方法(Promise原型上面的方法)
tempP.then(function(){
console.log(arguments); // 会打印出一个类数组 ['执行了']
})
tempP.then(function(arg){
console.log(arg); // 会打印出“执行了” arg接收了resolve里面的参数
})
注意上面的代码我们可以看到,在我们new出一个实例化对象时,并没有调用,但是却自己执行了,所以在实际使用时,我们可以在函数中实例化promise对象,然后将其return出来,这样就可以控制其执行的时间,通过return出来的实例化对象,也可以使用Promise原型上的方法;代码如下:
function tempFunction(){
var tempP=new Promise(function(resolve,reject){
setTimeout(function(){
reslove('----接受----');
},2000);
});
return tempP; // 返回tempP实例,使其可以使用Promise原型上面的方法
}
tempFunction(); // 调用执行tempFunction函数 得到一个Promis对象
// 也可以直接这样调用
tempFunction().then(function(data){
console.log(data); // '----接受----'
});
Promise的链式操作
promise对于多重回调写法非常简单,其传递状态以及维护状态的方式使得回调函数可以及时被调用,结构代码如下:
function method1(){// 方法1
var p=new Promise(function(resolve,reject){
setTimeout(function(){
console.log('方法一执行完毕')
resolve('method1');
},2000);
});
return p; // 返回p实例对象
}
function method2(){// 方法二
var p=new Promise(function(resolve,reject){
setTimeout(function(){
console.log('方法二执行完毕')
resolve('method2');
},2000);
});
return p; // 返回p实例对象
}
function method3(){// 方法三
var p=new Promise(function(resolve,reject){
setTimeout(function(){
console.log('方法三执行完毕')
resolve('method3');
},2000);
});
return p; // 返回p实例对象
}
// ...
// 执行方法
method1()
.then(function(data){
console.log(data)// 此处接收的是方法一传递的状态
return method2()// 在回调中执行方法二
})
.then(function(data){
console.log(data)// 此处接收的是方法二传递的状态
return method3()// 在回调中执行方法三
})
.then(function(data){
console.log(data)// 此处接收的是方法三传递在状态
//...
})
// ...
打印结果如下:
如上面执行时的结构就是链式结构,当然这里我们在.then()中return出的是数据,在其后通过.then()就可以接收到;
Promise私有方法
resolve和reject使用
Promise构造函数接收一个函数作为参数,该函数有两个参数: resolve,reject;表示成功或者失败时执行的方法,如果成功就执行resolve,如果失败则执行reject;
function method(){
var p=new Promise(function(resolve,reject){
setTimeout(function(){
var tempValue = Math.random()
if(tempValue> 0.5) {
console.log('执行resolve')
resolve(tempValue)
}else {
console.log('执行reject')
reject('这个数我不要')
}
},2000);
});
return p; // 返回p实例对象
}
// 方法执行
method()
.then((data) => {
console.log(data) // 成功的结果
}, (rejected, data) => {
console.log(rejected) // 失败的结果
console.log(data)
})
从上面的代码可以看出,.then()接收两个参数,第一个是参数接收的resolve的结果,第二个参数接收的reject的结果;
catch方法
我们知道浏览器处理异常的方法try...catch(),有一场进入catch,不阻断后续程序的执行;那么Promise的catch方法也是这样的效果,用来指定接收reject的回调;如下
method()
.then((data) => {
console.log(data) // 成功的结果
})
.catch((rejected, data) => {
console.log(rejected) // 失败的结果
console.log(data)
})
all方法
构造函数的方法,只能构造函数使用,并行执行异步操作,并且等待所有的异步操作完成后,才执行后续的回调;
function f1() {
var p = new Promise(function(resolve, reject) {
setTimeout(function() {
console.log('方法一执行了')
resolve(1)
}, 2000)
})
return p
}
function f2() {
var p = new Promise(function(resolve, reject) {
setTimeout(function() {
console.log('方法二执行了')
resolve(2)
}, 3000)
})
return p
}
function f3() {
var p = new Promise(function(resolve, reject) {
setTimeout(function() {
console.log('方法三执行了')
resolve(3)
}, 1000)
})
return p
}
Promise.all([f1(), f2(), f3()])
.then(function(results) {
console.log(results)// 所有的异步结果
})
执行结果如下:
如上我们可以看出,all方法接收一个数组作为参数,数组中是所有的方法,而all执行完毕之后,.then
接收的也是一个数据数据,里面是所有异步方法的结果;
race方法
与all方法不同,all方法是等所有的异步方法执行完毕之后,也就是说等最后一个异步返回结果,all才会执行.then()方法,并接收结果;race方法则是取最快执行完毕的异步方法的结果为标准来执行.then中的回调函数;代码如下:
Promise.race([f1(), f2(), f3()])
.then(function(results) {
console.log(results)// 只有一个异步方法返回的结果,所以此时results不是数组
})
打印结果如下:
以上就是我个人参考他人文档对Promise的总结;