手写promise原理系列二:手写promise的关键逻辑梳理,promise用法原理
创始人
2024-06-02 19:01:13
0

文章目录

  • 一、如何改变promise的状态?
  • 二、一个promise指定多个成功或失败回调,都会调用么?
  • 三、改变promise状态和then中的回调函数谁先执行谁后执行?
  • 四、promise.then() 返回的 promise 对象的结果由什么决定?
  • 五、promise如何进行链式调用?
  • 六、如何中断promise链式调用?
  • 七、promise异常穿透(promise.catch())

书接上回,上一篇手写promise系列一:promise基础知识解析中讲解了一些promise的基础知识以及常用API的使用,这篇文章的重点在于深入了解promise的运行方式,梳理其中的关键性逻辑,为接下来正式手写promise做一些准备工作。

大家千万不要着急,当真正进入手写promise环节后,可能还需要不断返回当前篇章,仔细斟酌这其中字句,才能真正了解promise中的无穷奥妙,全是高阶函数以及你不知道的JavaScript

一、如何改变promise的状态?

改变promise状态有三种情况,如下:

  1. resolve() --> 成功 fulfilled
  2. reject() --> 失败 rejected
  3. throw --> 失败 rejected

throw 抛出异常示例:

let p = new Promise((resolve, reject) => {throw "error";  // 抛出一个字符串错误,内容为'error'
})
p.catch((reason) => { console.log(reason); })
console.log(p);

在这里插入图片描述

二、一个promise指定多个成功或失败回调,都会调用么?

成功回调示例:

let p = new Promise((resolve, reject) => {resolve("OK")
})
// 指定回调1
p.then(value => {console.log(value);console.log("111");
})
// 指定回调2
p.then(value => {console.log(value);console.log("222");
})

在这里插入图片描述

由上图可知then中指定的多个成功回调函数全部执行了。

失败回调示例:

let p = new Promise((resolve, reject) => {reject("NO")
})
// 指定回调1
p.then(value => {console.log(value);
}, reason => {console.log(reason);console.log("111");
})
// 指定回调2
p.then(value => {console.log(value);
}, reason => {console.log(reason);console.log("222");
})

在这里插入图片描述
由上图可知then中指定的多个失败回调函数全部执行了。

三、改变promise状态和then中的回调函数谁先执行谁后执行?

这里我之前看的时候有点蒙,后来整理了一下思路,先说结论:不管是同步改变状态,还是异步改变状态,永远是先改变状态,再执行then中的回调函数。

这个问题有两种情况需要说明,以 resolve() 为例:

  1. 同步执行改变状态,就是先执行resolve(),然后执行then中回调函数。
let p = new Promise((resolve, reject) => {resolve("OK");
})
p.then(value => {console.log(value);
})

按照代码执行顺序,从上往下执行,先执行 resolve("OK") ,然后执行 p.then(),因为没有其他同步代码,所以直接执行 then 中的回调函数,输出 value 值为 "OK"

  1. 异步执行改变状态,先执行 p.then() ,等待状态发生改变后,再回头执行then中的回调函数。
let p = new Promise((resolve, reject) => {setTimeout(()=>{resolve("OK");}, 1000)
})
p.then(value => {console.log(value);
})

上面使用了 setTimeout() 宏任务,延迟1s后改变状态。按照代码执行顺序,此时 p.then() 已经执行,但是因为状态还未改变,所以 p.then() 中的回调函数被缓存起来(then方法内部做了缓存处理),等待状态改变后再执行。此时1s过后,控制台输出 value 的值为 "OK"

四、promise.then() 返回的 promise 对象的结果由什么决定?

先明确一点,函数中若无 return 语句,则函数的默认返回值为 undefined 。这个想必大家应该都清楚!

接下来说明 then 返回的 promise 对象的结果由什么决定?

  1. 如果抛出异常,则 then 返回的 promise 对象结果为 rejected 失败。
let p = new Promise((resolve, reject) => {resolve("OK")
})
let result = p.then(value => {throw "error";  	 // 抛出异常
})
result.catch(reason => {console.log(reason); // "error"
})
console.log(result);  	 // result为then返回的promise对象

在这里插入图片描述

  1. 如果返回的是非 promise 类型的任意值,promise对象的结果为 fulfilled 成功。
let p = new Promise((resolve, reject) => {resolve("OK")
})
let result1 = p.then(value => {console.log(value);
})
let result2 = p.then(value => {return "111";
})
console.log(result1);
console.log(result2);

在这里插入图片描述

  1. 如果返回的是一个 promise 对象,则此 promise 对象的结果就是 then 返回的 promise 对象的结果。
let p = new Promise((resolve, reject) => {resolve("OK")
})
let result1 = p.then(value => {return new Promise((resolve, reject)=>{resolve("成功啦")})
})
let result2 = p.then(value => {return new Promise((resolve, reject)=>{reject("失败啦")})
})
console.log(result1);
console.log(result2);

在这里插入图片描述

五、promise如何进行链式调用?

因为 promis e的 then 方法返回的是一个新的 promise 对象,所以可以再一次调用 then 方法,形成链式调用。本质就是套娃!

let p = new Promise((resolve, reject) => {resolve("OK")
})
let result = p.then(value => {console.log(value);	// OK
}).then(value => {console.log(value);	// undefinedreturn "111";
}).then(value => {return null;
})
console.log(result);	// 成功的promise对象,结果值为null

在这里插入图片描述

六、如何中断promise链式调用?

方法:返回一个 pending 状态的 promise 对象。

let p = new Promise((resolve, reject) => {
resolve("OK")
})
let result = p.then(value => {console.log(value);  			// "OK"return new Promise(() => {});  // 返回一个未改变状态的promise对象,中断then链式调用
}).then(value => {console.log(value);  // 无法打印return "222"
}).then(value => {console.log(value);	// 无法打印return "333"
})
console.log(result);  	// result是一个pending状态的promise对象

在这里插入图片描述

七、promise异常穿透(promise.catch())

promise 异常穿透,就是在使用 promise.then() 方法时,在链式调用最后面指定失败的回调 promise.catch() 。前面任何操作出现了异常,都会被传递到最后失败的回调处理中。

promise.catch() 方法的返回值为一个新的 promise 对象,返回结果与上面 promise.then() 的返回结果描述一致

let p = new Promise((resolve, reject) => {resolve("OK")
})
let result = p.then(value => {console.log(value);	 // "OK"throw "ERROR";		 // 抛出异常
}).then(value => {console.log(value);  // 不会打印return "111";
}).then(value => {console.log(value);  // 不会打印return null;
}).catch(reason => {console.log(reason); // "ERROR"
})
console.log(result);     // result是调用catch方法返回的新promise对象 

在这里插入图片描述

相关内容

热门资讯

“倾听您的心声,服务您的需求”... 中国人民人寿保险股份有限公司(以下简称“人保寿险”)“倾听您的心声 服务您的需求”第十七届客户节于2...
佩斯科夫:俄不会对媒体有关俄乌... 转自:财联社【佩斯科夫:俄不会对媒体有关俄乌谈判报道发表评论】财联社5月18日电,据塔斯社当地时间1...
穆杰,调任新职 编辑 | 余晖山东省人民政府近日发布任免通知,山东省人民政府决定,任命穆杰为山东省煤田地质局副局长。...
融合文化、体育与生态,房山举办... 新京报讯(记者陈璐)5月18日,“登峰揽胜在房山”山地绿道徒步活动在房山区周口店镇永寿禅寺广场启幕。...
5月19日,“同”赴一场有“法... 【5月19日,“同”赴一场有“法”的旅行】锦绣河山,美好旅程。在第15个中国旅游日,人民法院新闻传媒...
探索电影+旅游的创新合作,盐城... 转自:上观新闻当120年胶片齿轮撞上Z世代的赛博心跳,一座城正用“轻舟计划”重构青年与电影的时空契约...
十位艺术大师联袂,绘就江南诗意... 转自:上观新闻艺术的笔触邂逅江南的灵韵,共赏“吴越江南”的水墨诗意。近日,位于闵行区万源路2800号...
痛惜!突发呼吸心跳骤停,他于深... 南京艺术学院5月17日发布讣告:南京艺术学院教授、博士生导师尹悟铭同志,因突发呼吸心跳骤停,经抢救无...
2024年我国卫星导航产业产值... 原标题:2024年我国卫星导航产业产值达5758亿元来源:人民日报客户端5月18日,中国卫星导航定位...
龙牙刀、结界兽、天元鼎……《哪... 新京报记者 展圣洁 编辑 白爽 校对 赵琳5月19日,年度重磅特展——“看·见殷商”展览将在北京大运...
中国铁建相关公司中标一项349... (转自:快查一企业中标了)快查APP显示,中国铁建相关公司中铁十八局集团有限公司于2025年5月15...
上海家庭医生签约数超1100万... 转自:中工网中新网上海5月18日电 (记者 陈静)家庭医生是居民健康的“第一道防线”。世界家庭医生日...
50多岁2女子无视预警爬野山被... 转自:京报网_北京日报官方网站 【#50多岁2女子无视预...
广东建工全资子公司中标一项31... (转自:快查一企业中标了)快查APP显示,广东建工相关公司广东省基础工程集团有限公司于2025年5月...
从工具到生态:金融科技的角色升... 转自:企业观察网数字金融,作为传统金融与现代信息技术深度融合的产物,正在重塑金融业务模式的底层逻辑。...
义乌至迪拜“铁海快线+中东快航... 5月18日,澎湃新闻(www.thepaper.cn)记者从中国铁路上海局集团有限公司(以下简称“上...
文化中国行|探寻国宝里的中国智... 03:12今年5月18日是第49个国际博物馆日。山西历史悠久,素有“地上文物看山西”的美誉。山西博物...
祝姜同学前程似锦!救人小伙姜昭... 来源:人民日报 【祝姜同学前程似锦!#救人小伙姜昭鹏完成...
印度南部一建筑起火,至少17人... 转自:上观新闻当地时间5月18日,印度南部特伦甘纳邦海得拉巴市一栋建筑发生火灾,目前已造成至少17人...
墨西哥海军船只撞上布鲁克林大桥... 转自:央视新闻  当地时间17日晚,一艘载有277人的墨西哥海军大型帆船在穿越美国纽约布鲁克林大桥时...