Promise/A+ 02
前言
面向对象的设计思想对于开发者更加友好,可进行数据封装、模块化复用、 降低代码的复杂度和维护成本
而Promis用于解决JS中的异步回调问题,它是面向对象设计思想在异步编程中的一种实践,包括类、实例、实例方法、类方法(静态方法)、状态封装等一些OOP概念
同时Promise 设计遵循Promise/A+ 规范,如果一个对象/函数(Thenable)满足该规范中关于 then 方法的行为定义,那么称它为Promise。
JavaScript中,其面向对象的本质是基于原型,通过构造函数来模拟“类”的概念(构造函数、实例、原型)。ES6推出后引入class关键字等语法糖,为JS提供更接近传统面向对象的语法结构。
Promise/A+ 规范
在Promise链中return一个值x,下一个Promise会变成什么状态? ——[[Resolve]](promise,x)
状态机
pending、fulfilled、rejected
- pending -> fulfilled / rejected
- fulfilled、rejected 状态下,状态固定,不可以变
then实例方法
- 负责外部监听Promsie的结果(消费者);一定返回一个新的Promise(链式)
- then接收两个回调:onFulfilled,onRejected(普通函数)
- then方法如果“回调”返回值,则值传给下一个then;抛出异常时,下一个then接收拒绝原因
注意:then可以接收成功和失败的情况,catch也可以捕获失败。
- then的失败回调,只能捕获它前一个Promise失败状态;无法捕获then成功回调函数(onFulfilled)中抛出的错误;
- catch可以捕获Promise链中所有上游的错误
- 错误捕获:就近原则 和 穿透原则
实现源码的分析
[[Resolve]](promise,x) 伪代码
- promise 和 x 指向同一个对象情况 : 返回TyperError,防止造成死锁
const p1 = new Promise((resolve, reject) => { setTimeout(() =>{ try{ resolve(p1) }catch(e){ console.log(e) } },100) }) p1.catch(err=>{console.log(err})- x是一个标准的promise情况:当前promise状态 跟随 返回的Promise状态
// 链式Promise: p1 和 p2、p3 const p1 = new Promise(resolve => { setTimeout(() => resolve("p1 完成"), 1000); }); p1.then(()=>{ return new Promise(resolve => setTimeout(resolve,1000,"OK")) // cb1 }).then(res => { console.log(res) })执行流程分析
第一步 注册并暂存:
p1.then() 动作创建 p2空容器;
注册回调函数【cb1】:
将回调函数(then的onfulfilled)和p2的的引用(resolve),放入 p1 内部列表。
第二步 状态变更与触发微任务:
p1对象的executor中异步函数完成,改变p1状态,存储值;
p1读取内部列表,将回调放入全局的微任务队列。
第二步:执行回调【 cb1】并return ,即Promise/A+中的x,是一个Promise对象
第三步:触发 [[Resolve]](p2,x)
第四步:链接下一个.then,重复上述操作
- x是一个thenable对象:跟随 Thenable 的执行结果
- x是一个普通值:当前Promise,立即变为fulfilled状态
Promise类
实例方法:then、catch、finally
类方法/静态方法:resolve、reject、all、allSettled、race、any
resolve方法
区分“状态” 和 “触发状态改变的函数”
resolve方法(类的constructor内)的实现过程分析:
- 先检查状态是否为pending
- 改变状态:pending -> fulfilled
- 存储值:保存传入的value,供后续.then()使用
- 触发微任务:将注册的回调函数,推入微任务队列
resolve参数:
- 普通值和对象:传递到then方法的参数中
- Promise对象:当前Promise等待传入的Promsie处理
- Thenable:等待then方法的处理
