手写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对象 

在这里插入图片描述

相关内容

热门资讯

Python|位运算|数组|动... 目录 1、只出现一次的数字(位运算,数组) 示例 选项代...
张岱的人物生平 张岱的人物生平张岱(414年-484年),字景山,吴郡吴县(今江苏苏州)人。南朝齐大臣。祖父张敞,东...
西游西后传演员女人物 西游西后传演员女人物西游西后传演员女人物 孙悟空 六小龄童 唐僧 徐少华 ...
名人故事中贾岛作诗内容简介 名人故事中贾岛作诗内容简介有一次,贾岛骑驴闯了官道.他正琢磨着一句诗,名叫《题李凝幽居》全诗如下:闲...
和男朋友一起优秀的文案? 和男朋友一起优秀的文案?1.希望是惟一所有的人都共同享有的好处;一无所有的人,仍拥有希望。2.生活,...
戴玉手镯的好处 戴玉手镯好还是... 戴玉手镯的好处 戴玉手镯好还是碧玺好 女人戴玉?戴玉好还是碧玺好点佩戴手镯,以和田玉手镯为佳!相嫌滑...
依然什么意思? 依然什么意思?依然(汉语词语)依然,汉语词汇。拼音:yī    rán基本解释:副词,指照往常、依旧...
高尔基的散文诗 高尔基的散文诗《海燕》、《大学》、《母亲》、《童年》这些都是比较出名的一些代表作。
心在飞扬作者简介 心在飞扬作者简介心在飞扬作者简介如下。根据相关公开资料查询,心在飞扬是一位优秀的小说作者,他的小说作...
卡什坦卡的故事赏析? 卡什坦卡的故事赏析?讲了一只小狗的故事, 我也是近来才读到这篇小说. 作家对动物的拟人描写真是惟妙...
林绍涛为简艾拿绿豆糕是哪一集 林绍涛为简艾拿绿豆糕是哪一集第三十二集。 贾宽认为是阎帅间接导致刘映霞住了院,第二天上班,他按捺不...
小爱同学是女生吗小安同学什么意... 小爱同学是女生吗小安同学什么意思 小爱同学,小安同学说你是女生。小安是男的。
内分泌失调导致脸上长斑,怎么调... 内分泌失调导致脸上长斑,怎么调理内分泌失调导致脸上长斑,怎么调理先调理内分泌,去看中医吧,另外用好的...
《魔幻仙境》刺客,骑士人物属性... 《魔幻仙境》刺客,骑士人物属性加点魔幻仙境骑士2功1体质
很喜欢她,该怎么办? 很喜欢她,该怎么办?太冷静了!! 太理智了!爱情是需要冲劲的~不要考虑着考虑那~否则缘...
言情小说作家 言情小说作家我比较喜欢匪我思存的,很虐,很悲,还有梅子黄时雨,笙离,叶萱,还有安宁的《温暖的玄》 小...
两个以名人的名字命名的风景名胜... 两个以名人的名字命名的风景名胜?快太白楼,李白。尚志公园,赵尚志。
幼儿教育的代表人物及其著作 幼儿教育的代表人物及其著作卡尔威特的《卡尔威特的教育》,小卡尔威特,他儿子成了天才后写的《小卡尔威特...
海贼王中为什么说路飞打凯多靠霸... 海贼王中为什么说路飞打凯多靠霸气升级?凯多是靠霸气升级吗?因为之前刚到时确实打不过人家因为路飞的实力...
运气不好拜财神有用吗运气不好拜... 运气不好拜财神有用吗运气不好拜财神有没有用1、运气不好拜财神有用。2、拜财神上香前先点蜡烛,照亮人神...