Promise的原理及其面试题(笔记)
异步处理的演化
JS实现异步的代码模型主要依托于回调
dom.addEventListener("click", function(e){
// 回调函数作为第二个参数传递,函数可接收一个参数
}, {
})
dom.onclick = function(e){
// 回调函数作为属性传递,函数可接收一个参数
}
fs.readFile("./txt", function(err, buffer){
// 回调函数作为最后一个参数传递,函数可接收两个参数
})
这种设计实际上是有缺陷的
-
没有统一的标准
-
容易陷入回调地狱(callback hell)
/* 异步任务:依次发送7次网络请求,拿到服务器数据 */ asyncConnect("地址1", (resp1) => { // to do something asyncConnect("地址2", (resp2) => { // to do something asyncConnect("地址3", (resp3) => { // to do something asyncConnect("地址4", (resp4) => { // to do something asyncConnect("地址5", (resp5) => { // to do something asyncConnect("地址6", (resp6) => { // to do something asyncConnect("地址7", (resp7) => { // to do something }); }); }); }); }); }); });
后来,JS社区提出了Promise A+
规范,希望把异步规范化,并消除回调地狱
再后来,ES6 官方标准中提出了 Promise API
来处理异步,它满足Promise A+
规范
由于异步处理变得标准了,就给ES官方提供了进一步改进的空间,于是在ES7中出现了新的语法async await
,它更加完美的解决了异步处理问题
![image-20200926101652977](https://i-blog.csdnimg.cn/blog_migrate/c6441fc2b759c4da17705124d5126d3c.png)
Promise的概念
一个promise就是一个对象,它表示一个异步任务
异步任务内部保存了它的进展状态,规范中约定有三种状态,不同的状态属于不同的阶段
![image-20200926102936776](https://i-blog.csdnimg.cn/blog_migrate/23f0e9a0bc9b178fa95404c584546025.png)
状态的转换
任务开始时,始终处于未决阶段的挂起状态
任务在未决阶段的时候,有能力将其推向已决。比如,当从服务器拿到数据后,我们就从未决阶段推向已决的resolved状态,如果网络不好,导致出错了,我们就从未决阶段推向已决的rejected状态
我们把从未决推向已决的resolved状态的过程,叫做resolve,从未决推向已决的rejected状态的过程,叫做reject
![image-20200926103458605](https://i-blog.csdnimg.cn/blog_migrate/b29ebb7bf57ce9c322989d7508682eb4.png)
这种状态和阶段的变化是不可逆的,也就是说,一旦推向了已决,就无法重新改变状态
任务完成后附带的数据
任务从未决到已决时,可能附带一些数据,比如:跑步完成后的用时、网络请求后从服务器拿到的数据
![image-20200926104053342](https://i-blog.csdnimg.cn/blog_migrate/40ca400567cd36cca5e66853b9b9fa46.png)
任务的后续处理
任务已决后(有了结果),可能需要进一步做后续处理
针对resolved的后续处理,称之为thenable,针对rejected的后续处理,称之为catchable
![image-20200926104458657](https://i-blog.csdnimg.cn/blog_migrate/aa93b242daea832571be7753b7b327f8.png)
Promise的基本使用
ES6 提供了一套API来适配上面提到的异步模型,这个API即Promise
var pro = new Promise(