异步解决方案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状态才会结束。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,919评论 6 502
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,567评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,316评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,294评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,318评论 6 390
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,245评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,120评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,964评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,376评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,592评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,764评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,460评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,070评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,697评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,846评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,819评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,665评论 2 354

推荐阅读更多精彩内容