异步解决方案Promise作用及API

说明

该笔记是学习了尚硅谷李强老师的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的执行流程

image.png

流程说明:
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状态才会结束。

你可能感兴趣的:(异步解决方案Promise作用及API)