什么是Promise?
首先Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大,它是一个构造函数,他本身有all,race,reject,resolve方法,原型上有then,catch等方法,可以再控制台打印看下
Promise对象有两个特点:
- 对象状态不受其他影响,Promise对象代表一个异步操作,它有三种状态,pending(进行中),fulfilled(已成功),rejected(已失败),只有异步操作可以决定当前是哪一种状态,任何其他操作都无法改变其状态。
- 一旦状态改变,就不能再变,任何时候都可以得到这个结果,Promise状态的改变,只有两种可能:一种是从pending变为fulfilled,一种就是从pending变为rejected。
Promise基本用法
var p=new Promise(function(reslove,reject){
if(/*操作成功*/){
reslove(xx)
}else{
reject(xx)
}
})
promise接受两个参数,一个是reslove,一个reject。
reslove就是把状态从pending转为fulfilled,再异步操作成功后调用,而reject就是把状态从pending转为rejected,和resolve相反,两种都可把操作结果作为参数,传递出去。
这时候,我们就可以用之前看到的原型的then方法了,then方法就是用来接受成功和失败状态的回调函数的,then方法接受两个回调函数,一个是成功的回调,一个是失败的回调(可选)。
var p=new Promise(function(reslove,reject){
reslove("哈哈,成功了")
})
p.then(function(data){
console.log(data)
},function(error){
console.log(error)
})
由于then方法返回了一个新的Promise实例,因此可以链式调用,这也就解决了回调地狱。
function runAsync1(){
var p=new Promise(function(reslove,reject){
setTimeout(function(){
reslove('xx1');
},2000)
})
return p;
}
function runAsync2(){
var p=new Promise(function(reslove,reject){
setTimeout(function(){
reslove('xx2');
},5000)
})
return p;
}
function runAsync3(){
var p=new Promise(function(reslove,reject){
setTimeout(function(){
reslove('xx3');
},2000)
})
return p;
}
runAsync1().then(function(data){
console.log(data);
return runAsync2()
}).then(function(data){
console.log(data);
return runAsync3()
}).then(function(data){
console.log(data);
})
//xx1
//xx2
//xx3
需要注意的是,Promise实例化后会立即执行的。
var p = new Promise(function(resolve, reject) {
console.log('Promise');
resolve();
});
p.then(function() {
console.log('resolved.');
});
console.log('Hi!');
//Promise
//Hi!
//resolved.
还需要注意的是,resolve之后,不会阻塞后面的代码运行的。
new Promise((resolve, reject) => {
resolve(1);
console.log(2);
}).then(r => {
console.log(r);
});
//2
//1
接下来就讲一下,catch()是用来干嘛的,它用来指定发生错误的回调函数。
var promise = new Promise(function(resolve, reject) {
resolve(x+1);
});
promise.then(function(data){
console.log(data)
}).catch(function(error) {
console.log(error);
});
如果状态已经发生改变,再不会抛出错误,如下直接走then方法。
var promise = new Promise(function(resolve, reject) {
resolve('ok');
throw new Error('test');
});
promise
.then(function(value) { console.log(value) })
.catch(function(error) { console.log(error) });
另外,catch只捕获函数体内的
var promise = new Promise(function(resolve, reject) {
resolve('ok');
setTimeout(function(){
throw new Error("错误")
},100)
});
promise
.then(function(value) { console.log(value) })
.catch(function(error) { console.log(error) });
Promise.all()
promise.all就是多个Promise实例并行执行,参数接受一个数组,需等到全部状态都变为fulfilled才输出。
function runAsync1() {
var p = new Promise(function (reslove, reject) {
setTimeout(function () {
reslove('xx1');
}, 2000)
})
return p;
}
function runAsync2() {
var p = new Promise(function (reslove, reject) {
setTimeout(function () {
reslove('xx2');
}, 500)
})
return p;
}
function runAsync3() {
var p = new Promise(function (reslove, reject) {
setTimeout(function () {
reslove('xx3');
}, 400)
})
return p;
}
Promise.all([runAsync1(),runAsync2(),runAsync3()]).then(function(data){
console.log(data);//['xx1','xx2','xx3']
})
需要注意的是,当一个被rejected,就会立即返回,then的结果是第一个被rejected的结果。
Promise.race()
promise.race同样是多个Promise实例并行执行,参数同样接受一个数组,和all不同的是,谁的状态先变为fulfilled,谁先返回并把结果传递给then。
Promise.race([runAsync1(),runAsync2(),runAsync3()]).then(function(data){
console.log(data);//xx1
})
Promise.resolve()
就是把现有对象转为promise对象,他有四种情况:
第一种:参数是promise实例,那么将不做任何改变,将其返回。
第二种,参数是thenable对象
thenable对象指的是带属性then的对象,那么Promise.resolve,会将其转为promise对象,并把状态变为resolved,执行它所定义的then方法。
var thenable = {
then: function(resolve, reject) {
resolve('执行我的吧');
}
};
var p1 = Promise.resolve(thenable);
p.then(function(value) {
console.log(value); //'执行我的吧'
});
第三种,参数不是thenable对象或根本不是对象
var p = Promise.resolve('Hello');
p.then(function (s){
console.log(s)
});
// Hello
第四种,就是无参数,其结果是直接返回一个
resolved
状态的 Promise 对象。
需要特别注意的是,promise.resolve的对象,是在本轮“事件循环”结束时,而不是下一轮事件开始时,之后我会专门写一篇关于eventloop的文章,不懂的朋友到时可以看下。
setTimeout(function () {
console.log('three');
}, 0);
Promise.resolve().then(function () {
console.log('two');
});
console.log('one');
// one
// two
// three
Promise.reject()
该方法也会返回一个新的 Promise 实例,该实例的状态为rejected,需要注意的是,该方法会原封不动地作为reject的理由,变成后续方法的参数。这一点和Promise.resolve方法不一致
var thenable = {
then(resolve, reject) {
reject('出错了');
}
};
Promise.reject(thenable)
.catch(e => {
console.log(e === thenable)
})
// true