Promise是什么
创建Promise对象
var promise = new Promise(function(resolve, reject) {
console.log('start')
var flag = 1 > 0
if(flag) {
resolve('resolve');
}
else {
reject('reject');
}
});
promise.then(function(result) {
console.log(result);
}, function(err) {
console.log(err);
});
复制代码
三种状态
- Fulfilled 为 已成功 的状态
- Rejected 为 已失败 的状态
- Pending 可以理解为 Promise 对象实例创建时候的 初始 状态
Promise概念
- Promise是个构造函数,所以创建Promise的方式是new Promise
- 状态一经改变不会在变
- Promise构造函数接受一个函数作为参数,该函数的两个参数分别是 resolve 和 reject。它们是两个函数
- Promise 创建后会立即执行,所以上面代码中的start会打印出来
- 因为Promise是处理异步操作的,所以所有的异步操作会等到当前所有同步任务执行完毕再去执行异步任务
resolve & reject
- resolve 函数的作用是,将Promise对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去
- reject 函数的作用是,将Promise对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去
- Promise实例生成以后,可以用then方法分别指定resolved状态和rejected状态的回调函数
- resolve & reject 是可以带参数的,如果携带参数,那么参数将会传递给回调函数,而reject的参数往往是Error对象的实例,表示抛出去的异常,而resolve不但可以接受普通的数据,而且还可以接受一个新的promise实例
then
p1.then(() => {
return 'helloworld';
}).then((result) => {
console.log(result);
return 520
}).then((result) => {
console.log(result);
});
复制代码
- then方法是定义在Promise的原型上
- 作用就是为了给promise状态发生改变时,调用回调函数
- then()方法可以进行链式调用,上一个then返回的可以作为下个then的一个函数的参数
- 这就体现了promise 解决异步操作强大的地方了,在每个then中去处理一个异步操作,当异步操作处理结束后返回,才进入下一个then(),这就相当于把一个个异步操作串了起来,按顺序执行
- 在then中返回的数据可以是普通的数据,也可以是promise对象
catch
let p = new Promise((resolve, reject) => {
resolve();
});
p.then(() => {
throw new Error('err');
}).catch((err) => {
console.log(err);
});
复制代码
- catch同样也是Promise原型上的方法
- .catch() 其实也是.then的另一种写法 .then(null,rejection)
- 当then中发生了异常,可以用.catch() 捕获异常,如果在promise的整个调用中没有捕获异常,promise不会将异常抛出.
- catch可以捕获整个then调用链的异常
- 所以通常在写promise实例的时候需要加入catch()调用
finally
- 这个越来越像java的try/catch/finally
- 这个方法是在es2018中加入的
- 作用就是,不管发生了什么,这个finally的回调函数肯定会执行
- finally的回调函数,是不接受参数的,也就是说他的执行与promise的状态是没有关系的
Promise Other API
Promise.all
let p1 = new Promise((resolve,reject) => {
//模拟做一些异步操作
setTimeout(function(){
console.log('1');
resolve('p1操作');
}, 1000);
})
let p2 = new Promise((resolve,reject) => {
//模拟做一些异步操作
setTimeout(function(){
console.log('2');
resolve('p2操作');
}, 1000);
})
let p3 = new Promise((resolve,reject) => {
//模拟做一些异步操作
setTimeout(function(){
console.log('3');
resolve('p3操作');
}, 1000);
})
Promise.all([p1, p2, p3])
.then(function(value){
console.log(value);
});
复制代码
- Promise.all方法可以将多个promise的实例,组合成一个新的promise对象
- 参数可以不是数组,但是必须具有Iterator接口,而且返回的每个成员都是Promise实例
- 而新的promise的状态:当这几个的状态都为resolve,时 新promise对象的状态才是resolve,否则有一个状态为reject的话,新promise的状态就是reject
- 这个方法很强大,all的作用其实就是相当于并行的处理多个promise, 当所有的promise都执行完了,才会进入then(),同时也会把这几个promise返回的数据以数组的方式传递给then
Promise.race
let p1 = new Promise((resolve,reject) => {
//模拟做一些异步操作
setTimeout(function(){
console.log('1');
resolve('p1操作');
}, 1000);
})
let p2 = new Promise((resolve,reject) => {
//模拟做一些异步操作
setTimeout(function(){
console.log('2');
resolve('p2操作');
}, 1000);
})
let p3 = new Promise((resolve,reject) => {
//模拟做一些异步操作
setTimeout(function(){
console.log('3');
resolve('p3操作');
}, 1000);
})
Promise.race([p1, p2, p3])
.then(function(value){
console.log(value);
});
复制代码
let p1 = new Promise((resolve,reject) => {
//模拟做一些异步操作
setTimeout(function(){
console.log('进行一个接口调用,等待返回数据');
resolve('调用接口');
}, 10000);
})
let p2 = new Promise((resolve,reject) => {
//模拟做一些异步操作
setTimeout(function(){
console.log('如果p1 5s 还没有相应,那么就执行这个操作');
resolve('接口调用失败,进行操作');
}, 5000);
})
Promise.race([p1, p2])
.then(function(value){
console.log(value);
});
复制代码
- Promise.race跟all 类似, 也是将多个promise的实例组合成一个promise对象
- 区别在于新promise的状态为这些promise中第一个状态被修改的promise的状态,rece也就是说谁跑的快就是谁,那个率先改变的 Promise 实例的返回值,就传递给p的回调函数
- 这回返回的数据就不是数组了,而是第一个返回的resolve中传递的数据
Promise.resolve
如果想把一个对象转换成为一个Promise对象可以使用 Promise.resolve() 他的参数可以有三种可能
- 是一个Promise实例,如果是一个promise实例,那么Promise.resolve 将不做任何修改,直接返回这个实例
- 如果参数是个thenable对象,也就是说对象中有then方法,Promise.resolve 把这个对象转换成promise对象时,会立即调用里面的then方法
- 参数根本就不是对象的时候,Promise.resolve 会把它变成一个Promise对象,并且状态为resolved
- 当创建的promise实例不存在异步操作,则返回的promise实例一出生状态就是resolved,所以立即会调用回调函数
Promise.reject
也是返回一个promise实例,不用的是返回的实例的状态为reject