图示
代码
//定义三种状态
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
//平常用 promise 都是通过new 关键字来 new Promise(),所以应该用构造函数或者 class 实现
class MPromise{
/**如果在异步情况下,我们要先拿到所有 callback,然后才能在某个时机去执行,这里建立两个数组用来存储成功和失败的回调,
调用 then 的时候, 如果还是 pending 就存入数组 */
FULFILLED_CALLBACK_LIST = [];
REJECTED_CALLBACK_LIST = [];
_status = PENDING;
//入参是一个函数,函数接收 resolve 和 reject 两个参数
//注意在初始化 promise 的时候,就用执行这个函数, 并且有任何报错都要通过 reject 跑出去
constructor(fn){
//设置初始状态为 pending
this.status = PENDING;
this.value = null;
this.reason = null;
try{
fn(this.resolve.bind(this), this.reject.bind(this));
} catch(e){
this.rejected(e);
}
}
/** 在status 发生变化的时候,就执行所有回调.这里咱们用的 es6 的 getter 和 setter,更符合语义 */
get status(){
return this._status;
}
set status(newStatus){
this._status = newStatus;
switch (newStatus){
case FUFILLED:
this.FULFILLED_CALLBACK_LIST.forEach(callback=>{
callback(this.value)
})
break;
case REJECTED:
this.RECJECTED_CALLBACK_LIST.forEach(callback=>{
callback(this.reason)
})
break;
}
}
//根据规范,resolve()和 reject()这两个方法是要改 status的,从 pending 态改到 fulfilled/rejected 态
resolve(value){
if(this.status === PENDING){
this.value = value;
this.status = FULFILLED;
}
}
reject(reason){
if(this.status === PENDING){
this.reason = reason;
this.status = REJECTED;
}
}
//接收两个参数 onFulfilled, onRedjected
then(onFulfilled, onRejected){
//检查处理参数,如果不是 function,就忽略. 这个忽略指的是原样返回 value/reason
//如果onFulfilled不是函数,且 promise1 成功执行,promise2 必须成功执行并返回相同的值
const realOnFulfilled = this.isFunction(onFulfilled) ? onFulfilled : value=>value
//如果onRejected不是函数,且 promise1 拒绝执行,promise2 必须拒绝执行并返回相同的拒因
const realOnRejected = this.isFunction(onRejected) ? onRejected : reason=>reason
//then的返回值是一个 promise, 如果onFulfilled,onRedjected抛出一个异常 e, 则
promise2 必须拒绝执行, 并返回拒因e
const promise2 = new MPromise((resolve, reject)=>{
//规范中提到, onFulfilled 应该是微任务,所以用 queueMircotask调用
const fulfilledMicrotask=()=>{
queueMircotask(()=>{
try{
const x = realOnFulfilled(this.value);
//如果 onFulfilled 返回一个值 x,则运行resolvePromise
this.resolvePromise(promise2, x, resolve, reject);
}catch (e){
reject(e)
}
})
};
//规范中提到, onRejected 应该是微任务,所以用 queueMircotask调用
const rejectedMicrotask=()=>{
queueMicrotask(()=>{
try{
const x = realOnRejected(this.reason);
//如果 onRejected 返回一个值 x,则运行resolvePromise
this.resolvePromise(promise2, x, resolve, reject);
} catch(e){
reject(e)
}
})
};
//根据当前 promise 的状态,调用不同的函数
switch(this.status){
case FULFILLED:
fulfilledMicrotask()
break;
case REJECTED:
rejectedMicrotask()
break;
case PENDING:
this.FULFILLED_CALLBACK_LIST.push(fulfilledMicrotask)
this.REJECTED_CALLBACK_LIST.push(rejectedMicriotask)
}
})
return promise2
}
catch(onRejected){
return this.then(null, onRejected);
}
isFunctions(param){
return typeof param === 'function';
}
resolvePromise(promise2, x, resolve, reject){
//如果newPromise 和 x 只想同一对象, 以 TypeError 为拒因执行 newPromise
//这是为了防止死循环
if(promise2 === x){
return reject(new TypeError('The Promise and the return value are the same'));
}
if(x instanceof MPromise){
//如果 x 为 Promise, 则是 newPromise 接受 x 的状态
//也就是继续执行 x,如果执行的时候拿到一个 y,还要继续解析 y
queueMicrotask(()=>{
x.then((y)=>{
this.resolvePromise(promise2, y, resolve, reject);
},reject);
})
}else if (typeof x === 'object' || this.isFunction(x)) {
//如果 x 为对象或者函数
if(x === null){
// null 也会被判为对象
return resolve(x)
}
let then = null;
try{
//把 x.then 赋值给 then
then = x.then;
} catch (error){
//如果取 x.then的值抛出错误 e,则以 e 为拒因拒绝 promise
return reject(error);
}
//如果 then 是函数
if(this.isFunction(then)){
let called = false;
//将 x 作为函数的作用域 this 调用
//传递两个回调函数作为参数, 第一个参数叫做 resolvePromise,第二个参数叫做 rejectPromise
try{
then.call(
x,
//如果 resolvePromise 以值 y 为参数调用, 则运行 resolvePromise
(y)=>{
//需要一个变量 called 来保证只调用一次.
if(called) return;
called = true;
this.resolvePromise(promise2, y, resolve, reject);
},
//如果 rejectPromise 以拒因r 为参数被调用,则以拒因 r 拒绝 promise
(r)=>{
if(called) return;
called = true;
reject(r)
}
)
} catch(error){
//如果调用 then 方法抛出了异常 e
if(called) return;
//否则以 e 为拒因拒绝 promise
reject(error)
}
} else{
//如果 then 不是函数,以 x 为参数执行 promise
resolve(x)
}
} else{
//如果 x 部位对象或者函数, 以 x 为参数执行 promise
resolve(x);
}
}
//将现有对象转为Promise对象,如果 Promise.resolve 方法的参数,不是具有 then 方法的对象(又称 thenable 对象),则返回一个新的 Promise 对象,且它的状态为fulfilled。注意这是一个静态方法, 因为咱们是通过Promise.resolve调用的, 而不是通过实例去调用的.
static resolve(value){
if(value instanceof MPromise){
return value
}
return newPromise((resolve)=>{
resolve(value)
})
}
//返回一个新的Promise实例,该实例的状态为rejected。Promise.reject方法的参数reason,会被传递给实例的回调函数。
static reject(reason){
return new MPromise((resolve, reject)=>{
reject(reason)
})
}
`const p = Promise.race([p1,p2,p3])`
//该方法是将多个 Promise 实例,包装成一个新的 Promise 实例。只要p1、p2、p3之中有一个实例率先改变状态,p的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给p的回调函数。
static race(promiseList){
return newMPromise((resolve, reject)=>{
const length = promiseList.length;
if(length === 0){
return resolve()
}else {
for (let i = 0;i<length;i++) {
MPromise.resolve(promiseList[i]).then(
(value)=>{
return resolve(value)
}
(reason)=>{
return reject(reason)
}
)
}
}
})
}
}