说明
该笔记是学习了尚硅谷李强老师的Promise课程及结合阮一峰老师的ES6加上自己的理解整理的
1,Promise是什么?
1.1Promise的理解
1)抽象表达:Promise是JS中进行异步编程的新的解决方案,主要用来解决回调地狱的问题,可以有效的减少回调嵌套,并且异常可以统一处理,并且支持链式编程
2)具体表达:从语法上讲Promise是一个构造函数,从功能上讲Promise对象用来封装异步操作并获取其成功/失败的结果值
1.2promise的状态
对应实例对象的属性promiseState,它有三个值 :
1.pending:未决定「初始值」
2.resolved/fullfilled:成功
3.rejected:失败
状态改变
pending变为resolved. pending变为rejected
说明:只有这 2 种,情况, 且一个 promise 对象只能改变一次 无论变为resolved还是rejected, 都会有一个结果数据, 成功的结果数据一般称为 value, 失败的结果数据一般称为 reason
1.3promise的执行流程
流程说明:
new Promise((resolve,reject) =>{})
创建Promise实例的时候,构造函数接受一个函数作为参数,该函数也有2个参数resolve()为函数,成功时调用,改变pending状态为resolved,状态变为resolved时,then函数的第一个参数回调函数被调用
reject()为函数,失败时调用,改变pending状态为rejected,状态变为rejected时,then函数的第二个参数回调函数被调用或者catch的回调函数被调用
并且then函数,catch函数被调用后返回一个新的promise对象
1.4promise状态何时发生改变?
一共有三种情况可以使promise的状态发生改变
1.resolve被调用,状态变为resolved
2.reject被调用,状态变为rejected
3,throw抛异常,状态变为rejected
只有状态变成resolved/rejected后,then,catch中的回调函数才会被调用
1.5catch的穿透作用
then(value=>{},reason=>{})then函数的第二个回调函数可以用于处理异常,也可以使用catch统一处理异常
2者的区别:then的第二个回调处理异常,处理的是当前promise的返回的异常,而catch捕获异常具有穿透作用,前面任何一个then函数出现异常都可以捕获
问:两者一起用时,前者会生效(因为err已经将其处理,就不会再往下穿透)而走不到后面的catch
2Promise常用API及说明
2.1Promise构造函数:Promise(exector){}
(1)exector函数,执行器(resolve,reject)=>{}执行器函数属于同步执行
(2)resolve函数:PromiseState状态变为resolved时调用的函数value=>{}
(3)reject函数:PromiseState状态变为rejected时调用的函数reason=>{}
说明:Promise支持同步也支持异步
2.2Promise.prototype.then方法 (onResolved,onRejected)=>{}
1)onResolved 函数: 成功的回调函数 (value) => {}
2)onRejected 函数: 失败的回调函数 (reason) => {}
2.3Promise.prototype.catch 方法: (onRejected) => {}
onRejected 函数: 失败的回调函数 (reason) => {}
说明: then()的语法糖, 相当于: then(undefined, onRejected),
异常穿透使用:当运行到最后,没被处理的所有异常错误都会进入这个方法的回调函数中
说明:Promise.prototype.catch()方法是.then(undefined||null,rejection)的别名,用于指定发生错误时的回调函数
2.4Promise.prototype.finally 方法: ()=>{}
说明:方法的回调函数不需要参数。用于指定不管Promise对象最后状态如何,都会执行的操作
finally本质上是then方法的特例:
promise
.finally(() => {
// 语句
});
// 等同于
promise
.then(
result => {
// 语句
return result;
},
error => {
// 语句
throw error;
}
);
代码实现:
Promise.prototype.finally = function (callback) {
let P = this.constructor; //Promise
return this.then(
value => P.resolve(callback()).then(() => value),
reason => P.resolve(callback()).then(() => { throw reason })
);
};
不管前面的Promise是resolved还是rejected,都会执行回调函数callback并且总是返回原来的值
2.5Promise.resolve 方法 参数总类比较多,参照阮一峰老师的https://es6.ruanyifeng.com/#docs/promise#Promise-resolve
作用:直接将对象转化为Promise对象
Promise.resolve('foo')
// 等价于
new Promise(resolve => resolve('foo'))
2.6Promise.reject方法
返回一个promise实例,该实例的状态为rejected
const p = Promise.reject('出错了');
// 等同于
const p = new Promise((resolve, reject) => reject('出错了'))
p.then(null, function (s) {
console.log(s)
});
// 出错了
Promise.reject方法的参数会原封不动地作为reject的理由,变成后续方法的参数
Promise.reject('出错了')
.catch(e => {
console.log(e === '出错了')
})
// true
2.7Promise.all()
方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。
const p = Promise.all([p1,p2,p3]),其中参数p1,p2,p3都是promise的实例,如果不是可以用Promise.resolve方法包裹
p的状态p1,p2,p3决定,分为2种情况:
(1)只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数。
(2)只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。
使用注意事项:作为参数的promise实例,自己定义了catch方法,那么它一旦被rejected,并不会触发Promise.all()的catch方法,即如果参数中的实例定义了catch,即使rejected,也不会被promise.all的catch捕获到,得到结果超出预期
const p1 = new Promise((resolve, reject) => {
resolve('hello');
})
.then(result => result)
.catch(e => e);
const p2 = new Promise((resolve, reject) => {
throw new Error('报错了');
})
.then(result => result)
.catch(e => e);
Promise.all([p1, p2])
.then(result => console.log(result))
.catch(e => console.log(e));
// ["hello", Error: 报错了]
上面代码中,p1会resolved,p2首先会rejected,但是p2有自己的catch方法,该方法返回的是一个新的 Promise 实例,p2指向的实际上是这个实例。该实例执行完catch方法后,也会变成resolved,导致Promise.all()方法参数里面的两个实例都会resolved,因此会调用then方法指定的回调函数,而不会调用catch方法指定的回调函数。
2.8Promise.race()
Promise.race() 方法参数同样是多个promise实例,返回一个新的Promise实例
const p = Promise.race([p1,p2,p3])
说明:只要p1,p2,p3之中有一个实例率先改变状态。p的状态就跟着改变,那个率先改变的Promise实例的返回值,就传递给p的 回调函数
2.9.Promise.allSettled()
ES2020引入的用于确定一组异步操作是否都结束了(不管成功或失败)
Promise.allSettled()方法接受一个数组作为参数,数组的每个成员都是一个 Promise 对象,并返回一个新的 Promise 对象。只有等到参数数组的所有 Promise 对象都发生状态变更(不管是fulfilled还是rejected),返回的 Promise 对象才会发生状态变更。
注意:返回的新的promise实例的状态总是resolved,它的回调函数会接收到一个数组作为参数,该数组的每个成员对应前面数组的每个promise对象
const resolved = Promise.resolve(42);
const rejected = Promise.reject(-1);
const allSettledPromise = Promise.allSettled([resolved, rejected]);
allSettledPromise.then(function (results) {
console.log(results);
});
// [
// { status: 'fulfilled', value: 42 }, //异步操作的结果
// { status: 'rejected', reason: -1 }
// ]
2.10Promise.any()
ES2021 引入了Promise.any()
方法。该方法接受一组 Promise 实例作为参数,包装成一个新的 Promise 实例返回。
只要参数实例有一个变成fulfilled状态,包装实例就会变成fulfilled状态;如果所有参数实例都变成rejected状态,包装实例就会变成rejected状态。
Promise.any()跟Promise.race()方法很像,只有一点不同,就是Promise.any()不会因为某个 Promise 变成rejected状态而结束,必须等到所有参数 Promise 变成rejected状态才会结束。