根据PromiseA+规范从零实现Promise【这一次,带你彻底搞懂Promise使用和原理】

前言

Promise是什么?

  1. Promise是ECMA2015规范中推出的,用于异步编程的解决方案,从语法上讲Promise是一个对象,Promise内部可以保存异步操作的结果,创造Promise实例后,它会立即执行。可以通过自身then()方法获取成功或失败的结果。
  2. Promise为了解决传统异步代码的回调地狱问题,Promise也支持执行多个并发请求时,并在结束后获取执行结果。

一、术语

  1. promise是具有then方法的对象或函数,其行为符合此规范
  2. thenable是定义then方法的对象或函数
  3. value是任意合法的JavaScript值
  4. exception时使用throw语句抛出的值
  5. reason是表示promise为什么被rejected的值
// promise的基本示例
const promise = new Promise((resolve, reject) => {
  const num = Math.random();
  if (num > 0.5) resolve('成功了,当前随机数的值为:' + num);
  else reject('失败了,当前随机数的值为:' + num);
});
promise.then(
  res => { console.log('promise的状态是成功的,成功的值为' + res) },
  err => { console.log('promise的状态是失败的,失败的值为' + err) }
);

二、要求

  1. promise共三种状态: 请求态(pending) 完成态(fulfilled) 拒绝态(rejected)
  2. pending状态可以转为fulfilled或rejected
  3. 状态只能改变一次,已经修改不能再次更改

按照Promise要求定义自己的Promise构造函数和状态

// 为Promise定义常量
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
// 声明构造函数
class MyPromise{
	state = PENDING; // 初始化Promise的状态
	value = undefined; // Promise状态改为成功时的结果
	reason = undefined; // Promise状态改为失败时的结果
	constructor(exectuor){
		//创建Promise实例时 需调用Promise自身resolve() reject()方法
		exectuor(this.resolve.bind(this),this.reject.bind(this))
	}
	// 实现resolve方法
	resolve(value){
		// 调用resolve时 更改Promise的状态为fulfilled
		// 状态只能更改一次 当状态为初始状态时则更新状态
		if(this.state === PENDING){
			this.state = FULFILLED;
			this.value = value;
		}
	}
	// 实现reject方法
	reject(reason){
		// 调用reject时 更改Promise的状态为rejected
		// 状态只能更改一次 当状态为初始状态时则更新状态
		if(this.state === PENDING){
			this.state = REJECTED;
			this.reason = reason;
		}
	}
}

小结

  • 定义常量保存Promise的三种状态
  • 声明Promise的构造函数
  • 初始化Promise的状态,成功的结果,失败的结果
  • 创建Promise实例时需调用Promise自身的resolve()或reject()方法,更改Promise产生的结果和Promise的状态

三、then方法

  1. promise必须提供一个then方法来获取其当前或最终的value或reason,pormise的then方法接收两个参数

    promise.then(onFulfilled,onRejected)

  2. onFulfilled和onRejected都是可选参数
    2.1. 如果onFulfilled或onRejected不是一个函数,他必须被忽略
  3. 如果onFulfilled是一个函数
    3.1. 它必须在promise被fulfill后调用,promise的value是它的第一个参数。
    3.2. 它不能在promise被fulfill前调用。
    3.3. 它不能被调用超过一次。
  4. 如果onRejected是一个函数:
    4.1. 它必须在promise被rejected后调用,promise的reason是它的第一个参数。
    4.2. 它不能在promise被rejected前调用。
    4.3. 它不能被调用超过一次。
  5. onFulfilled或者onRejected在execution context仅包含平台代码之前不得被调用。
  6. onFulfilled和onRejected只能被作为函数调用
  7. 同一promise的then 可以被调用多次。
    7.1. 如果/当promise处于fulfilled状态,所有响应的onFulfilled回调必须按它们最初调用then的顺序执行
    7.2. 如果/当promise处于rejected状态,所有响应的onRejected回调必须按它们最初调用then的顺序执行
  8. then必须返回一个promise
    8.1. 如果(promise1的)onFulfilled或onRejected之一返回x, 执行Promise解析流程[[Resolve]](promise2, x)
    8.2. 如果(promise1的)onFulfilled或onRejected之一抛出一个异常e,promise2 必须以e作为reason被reject
    8.3. 如果(promise1的)onFulfilled不是一个函数且promise1变为fulfilled状态,promise2必须以和promise1相同的value被fulfill(大乐注:promise1的onFulfilled被忽略了)
    8.4. 如果(promise1的)onRejected不是一个函数且promise1变为rejected状态,promise2必须以和promise1相同的reason被reject(大乐注:promise1的onRejected被忽略了)

按照以上要求实现自己的then方法

class MyPromise {
  state = PENDING; // 初始化Promise的状态
  value = undefined; // Promise状态改为成功时的结果
  reason = undefined; // Promise状态改为失败时的结果
  onFulfilledCallbacks = []; // 保存then方法的成功回调
  onRejectCallbacks = []; // 保存then方法的失败回调
  constructor(exectuor) {
    //创建Promise实例时 需调用Promise自身resolve() reject()方法
    try {
      exectuor(this.resolve.bind(this), this.reject.bind(this));
    } catch (error) {
      this.reject(error);
    }
  }
  // 实现resolve方法
  resolve(value) {
    // 调用resolve时 更改Promise的状态为fulfilled
    // 状态只能更改一次 当状态为初始状态时则更新状态
    if (this.state === PENDING) {
      this.state = FULFILLED;
      this.value = value;
      this.onFulfilledCallbacks.forEach(fn => fn());
    }
  }
  // 实现reject方法
  reject(reason) {
    // 调用reject时 更改Promise的状态为rejected
    // 状态只能更改一次 当状态为初始状态时则更新状态
    if (this.state === PENDING) {
      this.state = REJECTED;
      this.reason = reason;
      this.onRejectCallbacks.forEach(fn => fn());
    }
  }
	// 实现then方法
	then(onFulfilled, onRejected) {
    // 2.1. 如果onFulfilled或onRejected不是一个函数,他必须被忽略
    onFulfilled = isFunction(onFulfilled) ? onFulfilled : value => value; // 向下传递value (then方法的穿透)
    onRejected = isFunction(onRejected)
      ? onRejected
      : err => {
          throw err;
        }; // 向下抛出抛出
    // then方法支持链式调用 then方法返回的是一个Promise
    const promise2 = new MyPromise((resolve, reject) => {
      // 它必须在promise被rejected后调用,promise的reason是它的第一个参数
      if (this.state === FULFILLED) {
        // then方法执行的是一个微任务这里使用queueMicrotask产生一个微任务
        queueMicrotask(() => {
          if (typeof onFulfilled === 'function') {
            try {
              // onFulfilled或onRejected之一返回x, 执行Promise解析流程[[Resolve]](promise2, x)
              const x = onFulfilled(this.value);
              resolvePromise(promise2, x, resolve, reject);
            } catch (error) {
              // onFulfilled或onRejected之一抛出一个异常e,promise2 必须以e作为reason被reject
              reject(error);
            }
          } else {
            // onFulfilled不是一个函数且promise1变为fulfilled状态,promise2必须以和promise1相同的value被fulfill(promise1的onFulfilled被忽略了)
            reject(this.value);
          }
        });
      }
      // 它必须在promise被rejected后调用,promise的reason是它的第一个参数。
      if (this.state === REJECTED) {
        // then方法执行的是一个微任务这里使用queueMicrotask产生一个微任务
        queueMicrotask(() => {
          if (typeof onRejected === 'function') {
            try {
              // onFulfilled或onRejected之一返回x, 执行Promise解析流程[[Resolve]](promise2, x)
              const x = onRejected(this.reason);
              resolvePromise(promise2, x, resolve, reject);
            } catch (error) {
              // onFulfilled或onRejected之一抛出一个异常e,promise2 必须以e作为reason被reject
              reject(error);
            }
          } else {
            // onRejected不是一个函数且promise1变为rejected状态,promise2必须以和promise1相同的reason被reject(promise1的onRejected被忽略了)
            reject(this.value);
          }
        });
      }
      // 如果调用then时Promise的状态依然为pending,则需要将onFulfilled和onRejected进行管理,并且状态被改变时调用(resolve和reject函数内)
      if (this.state === PENDING) {
        if (typeof onFulfilled === 'function') {
          // 7. 同一promise的then 可以被调用多次。
          // promise可以通过then方法调用多次 使用数组管理then方法产生的回调函数
          this.onFulfilledCallbacks.push(() => {
            queueMicrotask(() => {
              try {
                const x = onFulfilled(this.value);
                resolvePromise(promise2, x, resolve, reject);
              } catch (error) {
                reject(error);
              }
            });
          });
        }
        if (typeof onRejected === 'function') {
          // 7. 同一promise的then 可以被调用多次。
          // promise可以通过then方法调用多次 使用数组管理then方法产生的回调函数
          this.onRejectCallbacks.push(() => {
            queueMicrotask(() => {
              try {
                // onFulfilled或onRejected之一返回x, 执行Promise解析流程[[Resolve]](promise2, x)
                const x = onRejected(this.reason);
                resolvePromise(promise2, x, resolve, reject);
              } catch (error) {
                // onFulfilled或onRejected之一抛出一个异常e,promise2 必须以e作为reason被reject
                reject(error);
              }
            });
          });
        }
      }
    });
    return promise2;
  }
}

小结

  • then方法支持链式调用(返回的是一个promise)
  • then方法可以调用多次,使用数组去管理onFulfilled和onRejected
  • 当onFulfilled或onRejected不是函数时,直接忽略,onFulfilled返回value值,onRejected抛出错误reason
  • onFulfilled或onRejected必须在对应状态改变后执行
  • 使用queueMicrotask产生一个微任务
  • 使用resolvePromise完成Promise的解析流程(下文具体实现)

四、Promise流程解析

  • Promise解析流程指接收一个promise和一个任意值x作为输入的一个抽象流程,表示为[[Resolve]](promise, x)。如果x为thenable,它会尝试让promise继承x的状态,前提是x至少行为与promise有一定的相似。否则,它将以x作为value来fulfill这个promise。
  • 这种处理thenable的方式允许promise的不同实现互通,只要他们都暴露一个符合Promises/A+规范的then方法。它同时也能支持基于Promises/A+规范的实现与其它不规范但合理的实现(至少带有一个then方法)在一定程度上互相兼容
  • [[Resolve]](promise, x)按以下步骤执行:
    1. 如果promise和x引用同一个对象,以TypeError作为reason来reject这个promise
    2. 如果x是一个promise,接受它的状态
      2.1. 如果x处于pending状态,直到x变为fulfilled或rejected状态,promise必须保持pending状态。
      2.2. 如果/当x变为fulfilled状态,以相同的value来fulfill promise
      2.3. 如果/当x变为rejected状态,以相同的reason来reject promise
    3. 反之, 如果x是一个object或function
      3.1. 如果/当resolvePromise以y作为value被调用, 执行[[Resolve]](promise, y).
      3.2. 如果/当rejectPromise以r作为reason被调用, 以r为reason来reject promise.
      3.3. 如果resolvePromise和rejectPromise都被调用,或者同一个方法被调用了多次,以第一个调用为准,忽略其余调用
      3.4. 如果调用then抛出一个异常e:
          3.4.1. 如果resolvePromise已被调用过rejectPromise,忽略异常。
          3.4.2. 否则,以e作为reason来reject promise
      3.5. 把then设置成x.then
      3.6. 如果访问x.then属性导致抛出了一个异常(设为e),以e作为reason来reject promise
      3.7. 如果then是一个函数,以x作为this来调用它,并且传入两个参数resolvePromise和rejectPromise
      3.8. 如果then不是一个函数,以x作为value来fulfill promise
    4. 如果x不是object或function,将x作为value来fulfill promise。

    根据以上规范实现Promise的流程解析 (ResolvePromise)

    function resolvePromise(promise, x, resolve, reject) {
      // 1.如果promise和x引用同一个对象,以TypeError作为reason来reject这个promise
      if (promise === x) return reject(new TypeError('Chaining cycle detected for promise'));
      // 2. 如果x是一个promise,接受它的状态
      // 3. 反之, 如果x是一个object或function (此处判断包含 条件2 和条件3)
      let isCalled = false;
      if (isObject(x) || isFunction(x)) {
        try {
          // 3.5. 把then设置成x.then
          let then = x.then;
          // 3.7 如果then是一个函数,以x作为this来调用它,并且传入两个参数resolvePromise和rejectPromise
          if (isFunction(then)) {
            // 因为存在同名函数 这里使用resolvePromiseThen代替resolvePromise
            const resolvePromiseThen = y => {
              // 3.3. 如果resolvePromise和rejectPromise都被调用,或者同一个方法被调用了多次,以第一个调用为准,忽略其余调用
              if (isCalled) return;
              isCalled = true;
              // 3.1. 如果/当resolvePromise以y作为value被调用, 执行[[Resolve]](promise, y).
              resolvePromise(promise, y, resolve, reject);
            };
            // 使用rejectPromiseThen代替rejectPromise
            const rejectPromiseThen = r => {
              // 3.3. 如果resolvePromise和rejectPromise都被调用,或者同一个方法被调用了多次,以第一个调用为准,忽略其余调用
              if (isCalled) return;
              isCalled = true;
              reject(r);
            };
            then.call(x, resolvePromiseThen, rejectPromiseThen);
          } else {
            // 3.8. 如果then不是一个函数,以x作为value来fulfill promise
            resolve(x);
          }
        } catch (error) {
          // 3.6. 如果访问x.then属性导致抛出了一个异常(设为e),以e作为reason来reject promise
          if (isCalled) return;
          isCalled = true;
          reject(error);
        }
      } else {
        // 4. 如果x不是object或function,将x作为value来fulfill promise。
        resolve(x);
      }
    }
    // 辅助函数
    function isPromise(value){
    	return !!value && (typeof value === "object" || typeof value === "function") && typeof value.then === "function"
    }
    function isObject(value){
    	return !!value && typeof value === 'object'
    }
    function isFunction(value){
    	return !!value && typeof value === 'function'
    }
    

    小结

    • resolvePromise函数用于Promise流程解析,参数为then函数返回的promise 结果x resolve() reject()
    • promise和x不能指向同一个引用地址
    • x可能是一个promise,是的话根据x的状态执行他或返回对应的结果
    • x可能是函数或对象(thenable),取then方法,判断then方法是不是函数
    • x作为then方法,以x作为this来调用它,并且传入resolvePromiseThen和rejectPromiseThen方法,获取执行结果

五、catch方法

  1. catch 方法可以用于您的promise组合中的错误处理
  2. 当Promise 被rejected时,被调用的一个Function。 该函数拥有一个参数:reason rejection 的原因。
  3. 如果 onRejected 抛出一个错误或返回一个本身失败的 Promise , 通过 catch() 返回的Promise 被rejected;否则,它将显示为成功(resolved)。

1. 使用示例

const promise = new Promise((resolve, reject) => {
  reject('错误的结果');
});
promise.then().catch(err => {
  console.log('err', err);
});

2. 实现过程

  /**
   * catch方法
   * 内部直接调用then方法 将回调函数传递到onRejected
   */
  catch(onRejected) {
    return this.then(undefined, onRejected);
  }

六、finally方法

  1. 方法返回一个Promise。无论结果promise的执行结果是fulfilled或rejected,都会执行指定的回调函数。
  2. 需要执行上一次promise的执行结果,方便在下一次then()方法中获取finally上层then返回的结果

1. 使用示例

const promise =  new Promise((resolve,reject)=>{
	resolve('成功')
})
promise.then(res=>{
	throw new Error('返回第一个错误')
}).finally(()=>{
	console.log('成功或失败都会执行')
}).then(()=>{},err=>{ 
	// 获取第一个then返回的错误结果
	console.log('err',err)
	throw new Error('返回第二个错误')
}).catch((err)=>{
	// 获取第二个错误结果
	console.log('catch',err)
})

2. 实现过程

finally(onFinally) {
  // 返回一个promise
  return new Promise((resolve, reject) => {
    // 判断上一个promise的状态
    console.log(this.state);
    if (this.state === FULFILLED) {
      queueMicrotask(() => {
        try {
          onFinally();
          resolve(this.value);
        } catch (error) {
          reject(error);
        }
      });
    }
    if (this.state === REJECTED) {
      queueMicrotask(() => {
        try {
          onFinally();
          resolve(this.reason);
        } catch (error) {
          reject(error);
        }
      });
    }
    if (this.state === PENDING) {
      this.onFulfilledCallbacks.push(() => {
        queueMicrotask(() => {
          try {
            onFinally();
            resolve(this.state === FULFILLED ? this.value : this.reason);
          } catch (error) {
            reject(error);
          }
        });
      });
    }
  });
}

七、静态resolve()

  1. 直接调用Promise.resolve方法.并产生一个成功的结果
  2. value可能存在的情况
    • 普通值和空值 - 使用resolve返回当前值
    • 是一个Promise实例 - 直接返回此结果
    • thenable对象

1. 使用示例

MyPromise.resolve(MyPromise.resolve(MyPromise.resolve('成功了')))
.then(res => {
  console.log(res);
})

2. 实现过程

static resolve(value) {
	// 是一个Promise实例 - 直接返回此promise
	if(value instanceof MyPromise) return value;
	// 返回一个新的promise
	return new MyPromise((resolve,reject)=>{
		// thenable对象调用自身then方法
		if(value && value.then && typeof value.then === 'function'){
			value.then(resolve,reject);
		}
		else resolve(value);
	})
}

八、静态reject()

  1. 直接调用Promise.reject方法.并产生一个失败的结果

1. 使用示例

MyPromise.reject('失败了')
.catch(err => {
  console.log(err);
})

2. 实现过程

static reject(value) {
	// 返回一个新的promise
	return new MyPromise((_,reject)=>{
		reject(value);
	})
}

九、all()

  1. 接收一个可迭代的集合对象(实现了iterable),并返回一个Promise实例
  2. 当前所有结果全部返回成功时,返回成功结果组成的数组
  3. 当任何一个promise执行失败时,返回第一个执行失败的结果

1. 使用示例

const p1 = Promise.resolve('成功1')
const p2 = Promise.resolve('成功2')
const p3 = new Promise((resolve,reject)=>{ setTimeout(()=>{ reject('失败3') },1000) })
Promise.all([p1,p2,p3])
.then(err => {
  console.log(err);
}).catch(err=>{
	console.log(err)
})

2. 实现过程

static all(promises) {
  return new MyPromise((resolve, reject) => {
    let result = []; // 返回的结果数组
    let index = 0; //计数器 全部执行完毕返回成功的结果
    let promise = null;
    for (let i = 0; i < promises.length; i++) {
      promise = promises[i];
      // 是Promise 则执行then方法并将结果保存到结果数组
      if (isPromise(promise)) {
        promise.then(data => {
          result[i] = data;
          if (++index === promises.length) resolve(result);
        }, reject);
      } else {
      	// 非promise 直接将当前值存入结果数组
        result[i] = promise;
      }
    }
  });
}

十、allSettled()

  1. 接收一个可迭代的集合对象(实现了iterable),全部执行完毕后返回一个Promise实例
  2. 返回多个对象组成的数组,通过status判断promise的执行状态
  3. 当任何一个promise执行失败时,返回第一个执行失败的结果

1. 使用示例

const p1 = Promise.resolve('成功1')
const p2 = Promise.resolve('成功2')
const p3 = new Promise((resolve,reject)=>{ setTimeout(()=>{ reject('失败3') },1000) })
Promise.all([p1,p2,p3])
.then(err => {
  console.log(err);
}).catch(err=>{
	console.log(err)
})

2. 实现过程

static allSettled(promises) {
  return new MyPromise((resolve, reject) => {
    let result = []; // 返回的结果数组
    let index = 0; //计数器 全部执行完毕返回成功的结果
    let promise = null;
    for (let i = 0; i < promises.length; i++) {
      promise = promises[i];
      // 是Promise 则执行then方法并将结果保存到结果数组
      if (isPromise(promise)) {
        promise.then(
          data => {
            result[i] = { status: FULFILLED, value: data };
            if (++index === promises.length) resolve(result);
          },
          reason => {
            result[i] = { status: REJECTED, reason: reason };
            if (++index === promises.length) resolve(result);
          }
        );
      } else {
        // 非promise 直接将当前值存入结果数组
        result[i] = promise;
      }
    }
  });
}

十一、race()

  1. 接收一个可迭代的集合对象(实现了iterable),并返回一个Promise
  2. 一旦迭代器中的某个promise解决或拒绝,返回的 promise就会解决或拒绝 (哪个执行的速度快,返回哪个)
  3. 如果传递的可迭代集合是空的,那么返回的promise状态为pending

1. 使用示例

const p1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject('失败1');
  }, 2000);
});
const p2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject('失败2');
  }, 1000);
});
const p3 = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject('失败3');
  }, 3000);
});
Promise.race([p1, p2, p3])
  .then(res => {
    console.log(res);
  })
  .catch(err => {
    console.log(err);
  });

2. 实现过程

static race(promises) {
  return new MyPromise((resolve, reject) => {
    for (let promise of promises) {
      if (isPromise(promise)) {
        console.log(promise.state);
        // 根据promise的状态返回对应的结果
        if (promise.state === PENDING) {
          promise.then(resolve, reject);
        }
        if (promise.state === FULFILLED) {
          promise.then(resolve);
        }
        if (promise.state === REJECTED) {
          promise.then(undefined, reject);
        }
      } else {
        reject(promise);
      }
    }
  });
}

十二、Promise完整代码

// 辅助函数
function isPromise(value) {
  return !!value && (typeof value === 'object' || typeof value === 'function') && typeof value.then === 'function';
}
function isObject(value) {
  return !!value && typeof value === 'object';
}
function isFunction(value) {
  return !!value && typeof value === 'function';
}
function resolvePromise(promise, x, resolve, reject) {
  // 1.如果promise和x引用同一个对象,以TypeError作为reason来reject这个promise
  if (promise === x) return reject(new TypeError('Chaining cycle detected for promise'));
  // 2. 如果x是一个promise,接受它的状态
  // 3. 反之, 如果x是一个object或function (此处判断包含 条件2 和条件3)
  let isCalled = false; // 此变量用于判断同一个方法是否调用多次
  if (isObject(x) || isFunction(x)) {
    try {
      // 3.5. 把then设置成x.then
      let then = x.then;
      if (isFunction(then)) {
        // 因为存在同名函数 这里使用resolvePromiseThen代替resolvePromise
        const resolvePromiseThen = y => {
          // 3.3. 如果resolvePromise和rejectPromise都被调用,或者同一个方法被调用了多次,以第一个调用为准,忽略其余调用
          if (isCalled) return;
          isCalled = true;
          // 3.1. 如果/当resolvePromise以y作为value被调用, 执行[[Resolve]](promise, y).
          resolvePromise(promise, y, resolve, reject);
        };
        // 使用rejectPromiseThen代替rejectPromise
        const rejectPromiseThen = r => {
          // 3.3. 如果resolvePromise和rejectPromise都被调用,或者同一个方法被调用了多次,以第一个调用为准,忽略其余调用
          if (isCalled) return;
          isCalled = true;
          reject(r);
        };
        // 3.7 如果then是一个函数,以x作为this来调用它,并且传入两个参数resolvePromise和rejectPromise
        then.call(x, resolvePromiseThen, rejectPromiseThen);
      } else {
        // 3.8. 如果then不是一个函数,以x作为value来fulfill promise
        resolve(x); // 此时x是普通值 直接返回结果
      }
    } catch (error) {
      // 3.6. 如果访问x.then属性导致抛出了一个异常(设为e),以e作为reason来reject promise
      if (isCalled) return;
      isCalled = true;
      reject(error);
    }
  } else {
    // 4. 如果x不是object或function,将x作为value来fulfill promise。
    resolve(x);
  }
}

// 为Promise定义常量
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
// 声明构造函数
class MyPromise {
  state = PENDING; // 初始化Promise的状态
  value = undefined; // Promise状态改为成功时的结果
  reason = undefined; // Promise状态改为失败时的结果
  onFulfilledCallbacks = []; // 保存then方法的成功回调
  onRejectCallbacks = []; // 保存then方法的失败回调
  constructor(exectuor) {
    //创建Promise实例时 需调用Promise自身resolve() reject()方法
    try {
      exectuor(this.resolve.bind(this), this.reject.bind(this));
    } catch (error) {
      this.reject(error);
    }
  }
  // 实现resolve方法
  resolve(value) {
    // 调用resolve时 更改Promise的状态为fulfilled
    // 状态只能更改一次 当状态为初始状态时则更新状态
    if (this.state === PENDING) {
      this.state = FULFILLED;
      this.value = value;
      this.onFulfilledCallbacks.forEach(fn => fn());
    }
  }
  // 实现reject方法
  reject(reason) {
    // 调用reject时 更改Promise的状态为rejected
    // 状态只能更改一次 当状态为初始状态时则更新状态
    if (this.state === PENDING) {
      this.state = REJECTED;
      this.reason = reason;
      this.onRejectCallbacks.forEach(fn => fn());
    }
  }
  // 实现then方法
  // 2. onFulfilled和onRejected都是可选参数
  then(onFulfilled, onRejected) {
    // 2.1. 如果onFulfilled或onRejected不是一个函数,他必须被忽略
    onFulfilled = isFunction(onFulfilled) ? onFulfilled : value => value; // 向下传递value (then方法的穿透)
    onRejected = isFunction(onRejected)
      ? onRejected
      : err => {
          throw err;
        }; // 向下抛出抛出
    // then方法支持链式调用 then方法返回的是一个Promise
    const promise2 = new MyPromise((resolve, reject) => {
      // 它必须在promise被rejected后调用,promise的reason是它的第一个参数
      if (this.state === FULFILLED) {
        // then方法执行的是一个微任务这里使用queueMicrotask产生一个微任务
        queueMicrotask(() => {
          if (typeof onFulfilled === 'function') {
            try {
              // onFulfilled或onRejected之一返回x, 执行Promise解析流程[[Resolve]](promise2, x)
              const x = onFulfilled(this.value);
              resolvePromise(promise2, x, resolve, reject);
            } catch (error) {
              // onFulfilled或onRejected之一抛出一个异常e,promise2 必须以e作为reason被reject
              reject(error);
            }
          } else {
            // onFulfilled不是一个函数且promise1变为fulfilled状态,promise2必须以和promise1相同的value被fulfill(promise1的onFulfilled被忽略了)
            reject(this.value);
          }
        });
      }
      // 它必须在promise被rejected后调用,promise的reason是它的第一个参数。
      if (this.state === REJECTED) {
        // then方法执行的是一个微任务这里使用queueMicrotask产生一个微任务
        queueMicrotask(() => {
          if (typeof onRejected === 'function') {
            try {
              // onFulfilled或onRejected之一返回x, 执行Promise解析流程[[Resolve]](promise2, x)
              const x = onRejected(this.reason);
              resolvePromise(promise2, x, resolve, reject);
            } catch (error) {
              // onFulfilled或onRejected之一抛出一个异常e,promise2 必须以e作为reason被reject
              reject(error);
            }
          } else {
            // onRejected不是一个函数且promise1变为rejected状态,promise2必须以和promise1相同的reason被reject(promise1的onRejected被忽略了)
            reject(this.value);
          }
        });
      }
      // 如果调用then时Promise的状态依然为pending,则需要将onFulfilled和onRejected进行管理,并且状态被改变时调用(resolve和reject函数内)
      if (this.state === PENDING) {
        if (typeof onFulfilled === 'function') {
          // 7. 同一promise的then 可以被调用多次。
          // promise可以通过then方法调用多次 使用数组管理then方法产生的回调函数
          this.onFulfilledCallbacks.push(() => {
            queueMicrotask(() => {
              try {
                const x = onFulfilled(this.value);
                resolvePromise(promise2, x, resolve, reject);
              } catch (error) {
                reject(error);
              }
            });
          });
        }
        if (typeof onRejected === 'function') {
          // 7. 同一promise的then 可以被调用多次。
          // promise可以通过then方法调用多次 使用数组管理then方法产生的回调函数
          this.onRejectCallbacks.push(() => {
            queueMicrotask(() => {
              try {
                // onFulfilled或onRejected之一返回x, 执行Promise解析流程[[Resolve]](promise2, x)
                const x = onRejected(this.reason);
                resolvePromise(promise2, x, resolve, reject);
              } catch (error) {
                // onFulfilled或onRejected之一抛出一个异常e,promise2 必须以e作为reason被reject
                reject(error);
              }
            });
          });
        }
      }
    });
    return promise2;
  }
  /**
   * catch方法
   * 内部直接调用then方法 将回调函数传递到onRejected
   */
  catch(onRejected) {
    return this.then(undefined, onRejected);
  }
  /**
   * finaly方法
   * 无论Promise的结果为成功或者失败 都会走到finally中,并将之前的结果原封不动的返回到下一次then中
   */
  finally(onFinally) {
    // 返回一个promise
    return new MyPromise((resolve, reject) => {
      // 判断上一个promise的状态
      if (this.state === FULFILLED) {
        queueMicrotask(() => {
          try {
            onFinally();
            resolve(this.value);
          } catch (error) {
            reject(error);
          }
        });
      }
      if (this.state === REJECTED) {
        queueMicrotask(() => {
          try {
            onFinally();
            resolve(this.reason);
          } catch (error) {
            reject(error);
          }
        });
      }
      if (this.state === PENDING) {
        this.onFulfilledCallbacks.push(() => {
          queueMicrotask(() => {
            try {
              onFinally();
              resolve(this.state === FULFILLED ? this.value : this.reason);
            } catch (error) {
              reject(error);
            }
          });
        });
      }
    });
  }
  /**
   * 静态resolve()
   * 返回一个新的promise对象
   * 可以直接使用构造函数调用此方法,并产生一个成功的结果
   */
  static resolve(value) {
    if (value instanceof MyPromise) return value;
    // 返回一个新的promise
    return new MyPromise((resolve, reject) => {
      // 可能是thenable
      if (value && value.then && typeof value.then === 'function') {
        value.then(resolve, reject);
      } else resolve(value);
    });
  }
  /**
   * 静态reject方法
   */
  static reject(value) {
    // 返回一个新的promise
    return new MyPromise((_, reject) => {
      reject(value);
    });
  }
  /**
   * all方法
   * 接收一个可迭代的集合对象(实现了iterable),并返回一个Promise
   * 当前所有结果全部返回成功时,返回成功结果组成的数组
   * 当任何一个promise执行失败时,返回第一个执行失败的结果
   * 集合内的元素是promise时,执行promise.then()方法,否则直接返回这个元素
   */
  static all(promises) {
    return new MyPromise((resolve, reject) => {
      let result = []; // 返回的结果数组
      let index = 0; //计数器 全部执行完毕返回成功的结果
      let promise = null;
      for (let i = 0; i < promises.length; i++) {
        promise = promises[i];
        // 是Promise 则执行then方法并将结果保存到结果数组
        if (isPromise(promise)) {
          promise.then(data => {
            result[i] = data;
            if (++index === promises.length) resolve(result);
          }, reject);
        } else {
          // 非promise 直接将当前值存入结果数组
          result[i] = promise;
        }
      }
    });
  }

  /**
   * allSelled
   * 接收一个可迭代的集合对象(实现了iterable),并返回一个Promise
   * 返回多个对象组成的数组,通过status判断promise的执行状态
   */
  static allSettled(promises) {
    return new MyPromise((resolve, reject) => {
      let result = []; // 返回的结果数组
      let index = 0; //计数器 全部执行完毕返回成功的结果
      let promise = null;
      for (let i = 0; i < promises.length; i++) {
        promise = promises[i];
        // 是Promise 则执行then方法并将结果保存到结果数组
        if (isPromise(promise)) {
          promise.then(
            data => {
              result[i] = { status: FULFILLED, value: data };
              if (++index === promises.length) resolve(result);
            },
            reason => {
              result[i] = { status: REJECTED, reason: reason };
              if (++index === promises.length) resolve(result);
            }
          );
        } else {
          // 非promise 直接将当前值存入结果数组
          result[i] = promise;
        }
      }
    });
  }
  /**
   * race
   * 接收一个可迭代的集合对象(实现了iterable),并返回一个Promise
   * 一旦迭代器中的某个promise解决或拒绝,返回的 promise就会解决或拒绝 (哪个执行的速度快,返回哪个)
   * 如果传递的可迭代集合是空的,那么返回的promise状态为pending
   */
  static race(promises) {
    return new MyPromise((resolve, reject) => {
      for (let promise of promises) {
        if (isPromise(promise)) {
          // 根据promise的状态返回对应的结果
          if (promise.state === PENDING) {
            promise.then(resolve, reject);
          }
          if (promise.state === FULFILLED) {
            promise.then(resolve);
          }
          if (promise.state === REJECTED) {
            promise.then(undefined, reject);
          }
        } else {
          reject(promise);
        }
      }
    });
  }
}

/**
 * 测试Promise程序
 * yarn add promises-aplus-tests
 * npx promises-aplus-tests promise.js(当前文件名)
 */
MyPromise.defer = MyPromise.deferred = function() {
  let dfd = {};
  dfd.promise = new MyPromise((resolve, reject) => {
    dfd.resolve = resolve;
    dfd.reject = reject;
  });
  return dfd;
};
module.exports = MyPromise;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值