Promise的实现首先分为三部分:
- promise的状态控制
- promise的后续处理
- Promise的串联
promise的API分为原型成员(实例成员)和构造函数成员(静态成员)
-
原型成员
- then:注册一个后续处理函数,当Promise为resolved状态时运行该函数
- catch: 注册一个后续处理函数,当Promise为rejected状态时运行该函数
- finally:[ES2018]注册一个后续处理函数(无参),当Promise为已决时运行该函数
-
构造函数成员
- resolve(数据):该方法返回一个resolved状态的Promise,传递的数据作为状态数据,如果传递的数据是Promise,则直接返回传递的Promise对象
- reject(数据):该方法返回一个rejected状态的Promise,传递的数据作为状态数据
- all(iterable):这个方法返回一个新的promise对象,该promise对象在iterable参数对象里所有的promise对象都成功的时候才会触发成功,一旦有任何一个iterable里面的promise对象失败则立即触发该promise对象的失败。这个新的promise对象在触发成功状态以后,会把一个包含iterable里所有promise返回值的数组作为成功回调的返回值,顺序跟iterable的顺序保持一致;如果这个新的promise对象触发了失败状态,它会把iterable里第一个触发失败的promise对象的错误信息作为它的失败错误信息。Promise.all方法常被用于处理多个promise对象的状态集合。
- race(iterable):当iterable参数里的任意一个子promise被成功或失败后,父promise马上也会用子promise的成功返回值或失败详情作为参数调用父promise绑定的相应句柄,并返回该promise对象
Promise状态控制实现
const MyPromise = (()=>{
const PENDING = "pending",
RESOLVED = "resolved",
REJECTED = "rejected",
PromiseStatus = Symbol("PromiseStatus"),
PromiseValue = Symbol("PromiseValue"),
changeStatus = Symbol("changeStatus");
return class MyPromise{
/**
* 改变当前Promise的状态
* @param {*} newStatus
* @param {*} newValue
* @param {*} queue
*/
[changeStatus](newStatus,newValue){
if(this[PromiseStatus !==PENDING]){
return;
}
this[PromiseStatus] = newStatus;
this[PromiseValue] = newValue;
}
constructor(executor){
this[PromiseStatus] = PENDING;
this[PromiseValue] = undefined;
const resolve = data =>{
this[changeStatus](RESOLVED,data)
}
const reject = err =>{
this[changeStatus](REJECTED,err)
}
try{
//实例化一个新的promise对象时会传递一个函数,该函数带有resolve和reject两个形参,并且会自动调用该函数
executor(resolve,reject);
}catch(err){
this[changeStatus](REJECTED,err)
}
}
}
})()
promise状态控制实现: 首先实例化一个promise对象时,需要传递一个函数,该函数带有两个形参resolve,reject, 在实例化过程中会自动调用该函数(executor),执行传递的函数,实例化后得到promise对象带有两个属性,PromiseStatue,promiseValue, 当在该函数的执行体内调用executor的参数时(resolve,reject),会执行构造函数内相应的函数
+Promise的后续处理
const MyPromise = (() => {
const PENDING = "pending",
RESOLVED = "resolved",
REJECTED = "rejected",
PromiseStatus = Symbol("PromiseStatus"),
PromiseValue = Symbol("PromiseValue"),
changeStatus = Symbol("changeStatus"),
//新增
thenables = Symbol("thenables"),
catchables = Symbol("catchables"),
settleHandler = Symbol('settleHandler')
return class MyPromise {
[changeStatus](newStatus, newValue,queue) {
if (this[PromiseStatus !== PENDING]) {
return;
}
this[PromiseStatus] = newStatus;
this[PromiseValue] = newValue;
//执行相应队列中的函数
queue.forEach(handler =>handler(newValue))
//这里会执行调用then/catch方法时还未达到已决状态时放入作业队列中的后续处理函数
}
constructor(executor) {
this[PromiseStatus] = PENDING;
this[PromiseValue] = undefined;
//新增
this[thenables] = [];
this[catchables] = [];
const resolve = data => {
//修改
this[changeStatus](RESOLVED, data,this[thenables])
}
const reject = err => {
//修改
this[changeStatus](REJECTED, err,this[catchables])
}
try {
//实例化一个新的promise对象时会传递一个函数,该函数带有resolve和reject两个形参,并且会自动调用该函数
executor(resolve, reject);
} catch (err) {
//修改
this[changeStatus](REJECTED, err,this[catchables])
}
}
/**新增
* promise的后续函数
* @param {*} handler 后续处理函数
* @param {*} immediatelyStatus 需要立即执行的状态
* @param {*} queue 作业队列
*/
[settleHandler](handler,immediatelyStatus,queue){
if(this[PromiseStatus] === immediatelyStatus){
setTimeout(()=>{
handler(this[PromiseValue])
})
}else{
queue.push(handler)
}
}
/**新增
* Promise原型上的then方法
* @param {*} thenable then的处理函数
* @param {*} catchable catch的处理函数,如果传递了话
*/
then(thenable, catchable) {
this[settleHandler](thenable,RESOLVED,this[thenables]);
this.catch(catchable);//该函数也会执行,但过不了settleHandler状态的一关,自然执行不了catch的后续处理函数
}
/**新增
* Promise原型上的catch方法
* @param {*} catchable catch的处理函数
*/
catch(catchable) {
this[settleHandler](catchable,REJECTED,this[catchables]);
}
}
})()
then,catch后续处理: 当调用then/catch方法时,then会接受2个后续处理函数(thenable和catchable),catch会接收一个后续处理函数(catchable) ,如果此时状态处于未决阶段时,会把后续处理函数放入到作业队列里(微队列),等到变成已决阶段时才会从作业队列里按排列顺序(changeStatue中执行)执行作业队列里面的后续处理函数 ,如果此时状态已经处于已决阶段,会直接运行该后续处理函数,如果还是处于未决阶段时(参数数据均来自已决阶段得到的数据)
+Promise的串联
const MyPromise = (() => {
const PENDING = "pending",
RESOLVED = "resolved",
REJECTED = "rejected",
PromiseStatus = Symbol("PromiseStatus"),
PromiseValue = Symbol("PromiseValue"),
changeStatus = Symbol("changeStatus"),
thenables = Symbol("thenables"),
catchables = Symbol("catchables"),
settleHandler = Symbol('settleHandler'),
linkPromise = Symbol('linkPromise')
return class MyPromise {
[changeStatus](newStatus, newValue,queue) {
if (this[PromiseStatus !== PENDING]) {
return;
}
this[PromiseStatus] = newStatus;
this[PromiseValue] = newValue;
//执行相应队列中的函数
queue.forEach(handler =>handler(newValue))
//这里会执行调用then/catch方法时还未达到已决状态时放入作业队列中的后续处理函数
}
constructor(executor) {
this[PromiseStatus] = PENDING;
this[PromiseValue] = undefined;
this[thenables] = [];
this[catchables] = [];
const resolve = data => {
this[changeStatus](RESOLVED, data,this[thenables])
}
const reject = err => {
this[changeStatus](REJECTED, err,this[catchables])
}
try {
//实例化一个新的promise对象时会传递一个函数,该函数带有resolve和reject两个形参,并且会自动调用该函数
executor(resolve, reject);
} catch (err) {
this[changeStatus](REJECTED, err,this[catchables])
}
}
/**
* promise的后续函数
* @param {*} handler 后续处理函数
* @param {*} immediatelyStatus 需要立即执行的状态
* @param {*} queue 作业队列
*/
[settleHandler](handler,immediatelyStatus,queue){
if(typeof handler !== 'function'){
return;
}
if(this[PromiseStatus] === immediatelyStatus){
setTimeout(()=>{
handler(this[PromiseValue])
})
}else{
queue.push(handler)
}
}
/**新增
* promise的串联:then/catch方法被调用后首先调用该函数,生成一个新的Promise对象并返回,
* 然后then/catch为了要确认自身状态,需要调用settleHandler查看后续处理函数的运行状况,(通过接收运行返回的结果),如果返回的结果是一个可以按照正常逻辑走下去的非promise对象,则then方法返回的新Promise状态为resolved,如果是一个不能按照正常逻辑走下去的非Promise对象,则then方法返回的新Promise状态为rejected,如果返回的是一个promise对象,新promise状态与该Promise状态的then方法返回的后续处理函数执行情况保持一致
* @param {*} thenalbe //then的后续处理函数
* @param {*} catchable //catch的后续处理函数
*/
[linkPromise](thenable, catchable){
function exec(data,handler,resolve,reject){
try{
const result = handler(data)//得到的result是后续处理函数返回的结果
if(result instanceof MyPromise){
result.then(d=>{
resolve(d)
},err=>{
reject(err)
})
}else{
resolve(result)
}
}catch(err){
reject(err)
}
}
return new MyPromise((resolve,reject)=>{
this[settleHandler](data=>{
exec(data,thenable,resolve,reject);
},RESOLVED,this[thenables])
this[settleHandler](reason=>{
exec(reason,catchable,resolve,reject);
},REJECTED,this[catchables])
})
}
/**修改
* Promise原型上的then方法
* @param {*} thenable then的处理函数
* @param {*} catchable catch的处理函数,如果传递了话
*/
then(thenable, catchable) {
return this[linkPromise](thenable,catchable);
}
/**修改
* Promise原型上的catch方法
* @param {*} catchable catch的处理函数
*/
catch(catchable) {
return this[linkPromise](undefined,catchable);
}
}
})()
3.串联Promise: 应用场景:当后续的Promise需要用到之前的Promise的处理结果时,需要Promise的串联
promise对象中,无论是then方法还是catch方法,他们都具有返回值,返回的是一个全新的promise对象(return new Promise),该Promise的状态取决于后续处理函数,
如果该后续处理函数还没执行,还在作业队列里,则返回的Promise的状态是挂起状态(pandding),如果该后续处理函数已经在执行,说明该then自身的Promise对象进入了
已决状态(resolve或reject),如果后续处理函数能顺利执行,并返回了值,则then方法创建的全新Promise的状态变为Resolve,(参数数据为then方法return回来的数据)
如果后续处理函数在执行过程中发生了错误,(有报错),则该全新的Promise进入reject状态,(参数数据为报错的数据)
如果前面的Promise的后续处理函数在能顺利执行后,返回的值是一个Promise对象,则返回的新的Promise状态和后续处理返回的Promise状态保持一致,
注意并不是跟返回的Promise的后续处理函数执行状态保持一致(意思就是状态重新配对 return 的promise对象的状态,之前的无效)
(参数来自 已决阶段的后续处理函数返回的参数)
至此,Promsie的功能基本实现。
const MyPromise = (() => {
const PENDING = "pending",
RESOLVED = "resolved",
REJECTED = "rejected",
PromiseStatus = Symbol("PromiseStatus"),
PromiseValue = Symbol("PromiseValue"),
changeStatus = Symbol("changeStatus"),
thenables = Symbol("thenables"),
catchables = Symbol("catchables"),
settleHandler = Symbol('settleHandler'),
linkPromise = Symbol('linkPromise')
return class MyPromise {
[changeStatus](newStatus, newValue,queue) {
if (this[PromiseStatus !== PENDING]) {
return;
}
this[PromiseStatus] = newStatus;
this[PromiseValue] = newValue;
//执行相应队列中的函数
queue.forEach(handler =>handler(newValue))
//这里会执行调用then/catch方法时还未达到已决状态时放入作业队列中的后续处理函数
}
constructor(executor) {
this[PromiseStatus] = PENDING;
this[PromiseValue] = undefined;
this[thenables] = [];
this[catchables] = [];
const resolve = data => {
this[changeStatus](RESOLVED, data,this[thenables])
}
const reject = err => {
this[changeStatus](REJECTED, err,this[catchables])
}
try {
//实例化一个新的promise对象时会传递一个函数,该函数带有resolve和reject两个形参,并且会自动调用该函数
executor(resolve, reject);
} catch (err) {
this[changeStatus](REJECTED, err,this[catchables])
}
}
/**
* promise的后续函数
* @param {*} handler 后续处理函数
* @param {*} immediatelyStatus 需要立即执行的状态
* @param {*} queue 作业队列
*/
[settleHandler](handler,immediatelyStatus,queue){
if(typeof handler !== 'function'){
return;
}
if(this[PromiseStatus] === immediatelyStatus){
setTimeout(()=>{
handler(this[PromiseValue])
})
}else{
queue.push(handler)
}
}
/**新增
* promise的串联:then/catch方法被调用后首先调用该函数,生成一个新的Promise对象并返回,
* 然后then/catch为了要确认自身状态,需要调用settleHandler查看后续处理函数的运行状况,(通过接收运行返回的结果),如果返回的结果是一个可以按照正常逻辑走下去的非promise对象,则then方法返回的新Promise状态为resolved,如果是一个不能按照正常逻辑走下去的非Promise对象,则then方法返回的新Promise状态为rejected,如果返回的是一个promise对象,新promise状态与该Promise状态的then方法返回的后续处理函数执行情况保持一致
* @param {*} thenalbe //then的后续处理函数
* @param {*} catchable //catch的后续处理函数
*/
[linkPromise](thenable, catchable){
function exec(data,handler,resolve,reject){
try{
const result = handler(data)//得到的result是后续处理函数返回的结果
if(result instanceof MyPromise){
result.then(d=>{
resolve(d)
},err=>{
reject(err)
})
}else{
resolve(result)
}
}catch(err){
reject(err)
}
}
return new MyPromise((resolve,reject)=>{
this[settleHandler](data=>{
exec(data,thenable,resolve,reject);
},RESOLVED,this[thenables])
this[settleHandler](reason=>{
exec(reason,catchable,resolve,reject);
},REJECTED,this[catchables])
})
}
/**修改
* Promise原型上的then方法
* @param {*} thenable then的处理函数
* @param {*} catchable catch的处理函数,如果传递了话
*/
then(thenable, catchable) {
return this[linkPromise](thenable,catchable);
}
/**修改
* Promise原型上的catch方法
* @param {*} catchable catch的处理函数
*/
catch(catchable) {
return this[linkPromise](undefined,catchable);
}
}
})()
其他API
- Promise.resolve()
static resolve(data){
if(data instanceof Mypromise){
return data
}else{
return new MyPromise((resolve,reject)=>{
resolve(data);
})
}
}
静态resolve方法,静态resolve方法接受一个参数,如果该参数不是Promise对象,返回一个resolve状态的新Promise 如果该参数是一个promise对象,直接返回该promise对象
- Promise.reject()
static reject(reason){
//写两个参数是因为这这是形参,真正的reject在第二位参数位置
return new MyPromise((resolve,reject)=>{
reject(reason)
})
}
静态reject方法:接收一个参数,返回一个reject状态的Promise对象
- Promise.race()
static race(proms){
return new Promise((resolve,reject)=>{
proms.forEach(pro=>{
pro.then(data=>{
resolve(data);
},err=>{
reject(err);
})
})
})
}
静态race方法:接受一个由promise对象组成的数组,返回一个首先到达已决阶段的promise对象
- Promise.all()
static all(proms) {
return new Promise((resolve, reject) => {
const results = proms.map(p => {
const obj = {
result: undefined,
isResolved: false
}
p.then(data => {
obj.result = data;
obj.isResolved = true;
//判断是否所有的全部完成
const unResolved = results.filter(r => !r.isResolved)
if (unResolved.length === 0) {
//全部完成
resolve(results.map(r => r.result));
}
}, reason => {
reject(reason);
})
return obj;
})
})
}
静态all方法:接受一个由promise对象组成数组,如果全部的Promise的状态都变为resolve,则返回一个resolve状态的Promise,并带上所有promise在resolve后传递的参数组成的数组,如果有一个promise状态报错或变为reject,则变成reject