使用Promise/A+ 规范,实现Promise

一、规范简介

  1. 术语:

    • Promise 是具有then方法的对象或函数,行为符合Promise/A+规范。
    • thenable 是定义then方法得对象或函数
    • value 是任何合法的Javascript值(包括undefined,ableable或promise)
    • 异常 exception throw 语句抛出的值
    • reason 是表明拒绝promise的原因
  2. 要求

    1. promise 的状态

      • pending:等待状态,可以转换成其他状态。
      • fulfilled:成功状态,不能转化为其他状态。转为该状态需要一个value,该value不能改变。
      • rejected:失败状态,不能转为其他状态。转为改状态需要一个reason,该reason不能改变。

      fulfilled与rejected是稳定状态

    2. then 方法

      • const promise2 = promise1.then(onFulfilled, onRejected)
      • then方法的参数
        • 两个函数参数
        • onFulfilled在promise完成后被调用,onRejected在Promise被拒绝执行后调用
        • 只能被调用一次
      • then方法的调用:可以调用多次
      • then方法的返回值:promise
        1. onFulfilled不是函数,promise1的状态是fulfilled :这时 promise2的状态是fulfilled,值同promise1
        2. onRejected不是函数,promise1的状态是rejected:这时promise2的状态是 rejected,拒绝原因reason同promise1
        3. onFulfilled 或者onRejected return x 返回一个返回值,进入Promise解析过程
    3. Promise解析过程

      • 抽象模型 resolve(promise, x)
      • 如果promise和x指向相同的对象
      • 如果x是一个promise:查看x的状态 pending 则需等待状态改变,fulfilled value 为 promise的值 ,reject reason为promise的reason
      • 如果x是一个对象或一个函数: 执行x的then方法
      • 如果x不是对象也不是函数:把x作为promise的值,设置成fulfilled状态

二、根据规范打造自己的Promise

  1. new Promise

    • 定义一个 class 来证明 promise

    • new Promise((resolve, reject) => {}),传入一个参数(函数),该函数为立即执行函数,这里面我们起名为 executor。

    • executor 函数接收两个参数,resolve 与 reject,成功时resolve(value),失败时reject(reason)。

    • promise 原型方法:

      • .then()
      • .catch()
      • .finally()
    • promise 静态方法

      • Promise.resolve(value)
      • Promise.reject(reason)
      • Promise.all([p1, .....,pn])
      • Promise.allSettled([p1, .....,pn])
      • Promise.race([p1, .....,pn])

    根据以上信息,我们大致架构如下

    class Promise {
      // 构造器
      constructor(executor) {
        // resolve()
        let resolve = value => {}
        // reject()
        let reject = reason => {}
        // 立即执行 executor 方法
        executor(resolve, reject);
      }
      // then 方法
      then() {}
      // catch 方法
      catch() {}
      // finall 方法
      finally() {}
    }
    
    Promise.resolve = () => {}
    Promise.reject = () => {}
    Promise.all = () => {}
    Promise.allSettled = () => {}
    Promise.race = () => {}
    
    
    
  1. promise 状态

    规范要求:Promise 状态

    • Promise 存在三个状态(state):pending,fulfilled,rejected
    • pending 为初始状态,可转化为 fulfilled 和 rejected
    • 成功后,不可转为其他状态,且需要一个不可变值(value)
    • 失败后,不可转为其他状态,且需要一个不可变原因(reason)

    new Promise((resolve, reject) => {})

    • 成功时 resolve(value),接受参数value,状态改为 fulfilled,此为稳定状态,不可再次改变。
    • 失败时 reject(reason),接受参数 reason,状态改为 rejected,此为稳定状态,不可再次改变。
    • 执行 executor 时报错,则直接执行 reject(reason)

根据以上信息,我们得到以下代码:

class Promise {
  // 构造器
  constructor(executor) {
    // 状态 默认为 pending 状态
    this.state = "pending";
    // 成功的值
    this.value = undefined;
    // 失败的原因
    this.reason = undefined;
    // resolve(value) 将状态改为 fulfilled 状态
    let resolve = value => {
      this.value = value;
      this.state = "fulfilled";
    }
    // reject(reason) 将状态改为 rejected 状态
    let reject = reason => {
      this.reason = reason;
      this.state = "rejected";
    }
    // 如果 executor 报错 立即执行 reject
    try{
      // 立即执行 executor 方法
      executor(resolve, reject);
    } catch(error) {
      reject(error);
    }
  }
  // then 方法
  then() {}
  // catch 方法
  catch() {}
  // finall 方法
  finally() {}
}

Promise.resolve = () => {}
Promise.reject = () => {}
Promise.all = () => {}
Promise.allSettled = () => {}
Promise.race = () => {}

  1. .then()方法

    规范要求:.then()

    由于.then()要求很多,我们进行拆解,分为:

    • 基本要求
    • 链式调用。

    1. 基本要求:

    • 一个 Promise 必须提供 then 方法,访问其当前或最终value或reason

    • then 接受两个参数 promise.then(onFulfilled, onRejected)

      • then的两个参数为可选参数。
      • 如果参数不是函数,则必须将其忽略。
      • 如果 onFulfilled 是函数
        • 必须在promise 成功后调用,以promise的值(value)作为第一个参数,不能调用多次。
      • 如果 onRejected 是函数
        • 必须在promise 失败后调用,以promise的原因(reason)作为第一个参数,不能调用多次。
      • onFulfilled 及 onRejected 必须作为函数调用(没有this值)
    • 异步调用:onFulfilled 或 onRejected 在执行上下文堆栈(紧包含平台代码)之前不能调用

    class Promise {
      // 构造器
      constructor(executor) {...}
      // then 方法
      then(onFulfilled, onRejected) {
        // onFulfilled 为可选参数 如果不为函数 则忽略onFulfilled 直接返回 value
        onFulfilled = isFunction(onFulfilled) ? onFulfilled : value => value;
        // onRejected 为可选参数 如果不为函数 则忽略onFulfilled 直接抛出错误
        onRejected = isFunction(onRejected) ? onRejected : error => { throw error};
        // 如果 Promise 为 成功状态 调用 onFulfilled 方法 传入成功的 value
        if(this.state === "fulfilled") {
          // 异步调用
          setTimeout(() => {
            onFulfilled(this.value);
          }, 0);
        }
        // 如果 Promise 为 失败状态 调用 onRejected 方法 传入失败的 reason
        if (this.state === "rejected") {
          // 异步调用
          setTimeout(() => {
            onRejected(this.reason);
          }, 0);
        }
      }
      // catch 方法
      catch() {}
      // finall 方法
      finally() {}
    }
    
    Promise.resolve = () => {}
    Promise.reject = () => {}
    Promise.all = () => {}
    Promise.allSettled = () => {}
    Promise.race = () => {}
    
    // 辅助方法
    // 判断 obj 是不是 Function
    function isFunction(obj) {
      return !!obj && typeof obj === "function";
    }
    // 判断 obj 是不是 Object
    function isObject(obj) {
      return !!obj && typeof obj === "object";
    }
    // 判断 obj 是不是 Promise
    function isPromise(obj) {
      return !!obj && (typeof obj === "object" || typeof obj === "function") && typeof obj.then === "function";
    }
    

    特殊情况:

    new Promise((resolve, reject) => {
      setTimeout(() => {
         resolve(1);
         // reject("错误");
      }, 200)
    })
    

    当 resolve 或者reject 在 setTimeout内执行时,由于setTimeout为异步方法,会先把它放到宏任务队列当中等待当前任务执行完成之后在执行。当前任务执行到.then 时 Promise的状态(state)还是pending(等待状态),这时就会出现问题。

    解决方案:

    规范要求中有一条要求:

    • then 可能在同一 Promise中多次被调用

      let p = new Promise();
      p.then();
      p.then();
      
      • 当promise 成功,则所有相应的 onFulfilled回调必须按照其原始调用的执行顺序执行then
      • 当promise失败,则所有相应的onRejected回调必须按照其原始调用的执行顺序进行then

    根据这一要求,我们可以在then中增加 state为pending的处理,将onFulfilled 与onRejected方法存到各自的数组里面,一旦setTimeout中的resolve或者reject执行了 ,就调用它们。

    这样除了能解决setTimeout异步问题,也能解决统一Promise多次调用then问题。

    根据以上信息,得到以下代码:

    class Promise {
      constructor(executor) {
        this.state = "pending";
        this.value = undefined;
        this.reason = undefined;
        // 成功存放方法的数组
        this.onResolvedCallbacks = [];
        // 失败存放方法的数组
        this.onRejectedCallbacks = [];
        let resolve = value => {
          this.value = value;
          this.state = "fulfilled";
          // 一旦 resolve 执行, 则按顺序 调用 成功数组 中的函数
          this.onResolvedCallbacks.forEach(fn => {
            fn();
          });
        }
        let reject = reason => {
          this.reason = reason;
          this.state = "rejected";
          // 一旦 reject 执行, 则按顺序 调用 失败数组 中的函数
          this.onRejectedCallbacks.forEach(fn => {
            fn();
          });
        }
        try{
          executor(resolve, reject);
        } catch(error) {
          reject(error);
        }
      }
      // then 方法
      then(onFulfilled, onRejected) {
        onFulfilled = isFunction(onFulfilled) ? onFulfilled : value => value;
        onRejected = isFunction(onRejected) ? onRejected : error => { throw error};
        if(this.state === "fulfilled") {
          setTimeout(() => {
            onFulfilled(this.value);
          }, 0);
        }
        if (this.state === "rejected") {
          setTimeout(() => {
            onRejected(this.reason);
          }, 0);
        }
        // 如果 Promise 为 等待状态 
        // 由于不知道 是成功还是失败,则需要两个数组,
        // 将成功或失败各自对应的方法 push 到各自的数组当中
        if (this.state === "pending") {
          // onFulfilled 传入到成功数组
          this.onResolvedCallbacks.push(() => {
            // 异步调用
            setTimeout(() => {
              onFulfilled(this.value);
            }, 0);
          });
          // onRejected 传入到成功的数组
          this.onRejectedCallbacks.push(() => {
            // 异步调用
            setTimeout(() => {
              onRejected(this.reason);
            }, 0);
          })
        }
      }
      catch() {}
      finally() {}
    }
    
    Promise.resolve = () => {}
    Promise.reject = () => {}
    Promise.all = () => {}
    Promise.allSettled = () => {}
    Promise.race = () => {}
    
    function isFunction(obj) {
      return !!obj && typeof obj === "function";
    }
    function isObject(obj) {
      return !!obj && typeof obj === "object";
    }
    function isPromise(obj) {
      return !!obj && (typeof obj === "object" || typeof obj === "function") && typeof obj.then === "function";
    }
    

    2. 链式调用

    日常使用 Promise 时,常用到 new promise().then().then(),这就是链式调用。通过链式调用,我们就可以解决回调地狱问题。

    规范中规定:

    1. then 必须返回一个promise

      promise2 = promise1.then(onFulfilled, onRejected);

      • 如果 onFulfilled 或 onRejected 执行时报错,则直接返回失败
      • onFulfilled 不是函数,promise1的状态是fulfilled :这时 promise2的状态是fulfilled,值同promise1
      • onRejected 不是函数,promise1 的状态是 rejected:这时promise2的状态是 rejected,拒绝原因 reason 同promise1
      • 如果一个 onFulfilled 或 onRejected 返回一个值 x(自己return x),则需要对x进行处理,处理的函数叫做:resolvePromise(promise2, x)
    2. 规范中的resolvePromise(promise2, x) 规定

      • 如果promise和x指向相同的对象,会导致循环调用,直接返回失败
      • 如果x是一个promise:查看x的状态 pending 则需等待状态改变,fulfilled value 为 promise的值 ,reject reason为promise的reason
      • 如果x是一个对象或一个函数: 执行x的then方法
        • 如果 没有x.then 则直接返回失败
        • 如果 有x.then 且为函数,则执行 then.call(),参数:x 作为this,成功时的回调,失败时的回调。
          • 如果成功的回调还是promise,值为y,再次调用 resolvePromise(promise2, y, resolve, reject)
          • 如果失败,则执行失败回到,原因为r,直接返回失败
          • 成功和失败只能调用一个,所以设定一个isCalled来防止多次调用
        • 如果 有x.then但不是函数,则将x作为promise的值
      • 如果x不是对象也不是函数:把x作为promise的值,设置成fulfilled状态
      class Promise {
        // 构造器
        constructor(executor) {...}
        // then 方法
        then(onFulfilled, onRejected) {
          // onFulfilled 为可选参数 如果不为函数 则忽略onFulfilled 直接返回 value
          onFulfilled = isFunction(onFulfilled) ? onFulfilled : value => value;
          // onRejected 为可选参数 如果不为函数 则忽略onFulfilled 直接抛出错误
          onRejected = isFunction(onRejected) ? onRejected : error => { throw error};
          // 如果 Promise 为 成功状态 调用 onFulfilled 方法 传入成功的 value
          if(this.state === "fulfilled") {
            // 异步调用
            setTimeout(() => {
              try {
                let x = onFulfilled(this.value);
                resolvePromise(promise2, x, resolve, reject);
              } catch (error) {
                reject(error);
              }
            }, 0);
          }
          // 如果 Promise 为 失败状态 调用 onRejected 方法 传入失败的 reason
          if (this.state === "rejected") {
            // 异步调用
            setTimeout(() => {
              try {
                let x = onRejected(this.reason);
                resolvePromise(promise2, x, resolve, reject);
              } catch (error) {
                reject(error);
              }
            }, 0);
          }
          // 如果 Promise 为 等待状态 
          // 由于不知道 是成功还是失败,则需要两个数组,
          // 将成功或失败各自对应的方法 push 到各自的数组当中
          if (this.state === "pending") {
            // onFulfilled 传入到成功数组
            this.onResolvedCallbacks.push(() => {
              // 异步调用
              setTimeout(() => {
                try {
                  let x = onFulfilled(this.value);
                  resolvePromise(promise2, x, resolve, reject);
                } catch (error) {
                  reject(error);
                }
              }, 0);
            });
            // onRejected 传入到成功的数组
            this.onRejectedCallbacks.push(() => {
              // 异步调用
              setTimeout(() => {
                try {
                  let x = onRejected(this.reason);
                  resolvePromise(promise2, x, resolve, reject);
                } catch (error) {
                  reject(error);
                }
              }, 0);
            });
          }
        }
        // catch 方法
        catch() {}
        // finall 方法
        finally() {}
      }
      
      Promise.resolve = () => {}
      Promise.reject = () => {}
      Promise.all = () => {}
      Promise.allSettled = () => {}
      Promise.race = () => {}
      
      function resolvePromise(promise2, x, resolve, reject) {
        // 如果 x 和 promise2 指向相同
        if (x === promise2) {
          reject(new TypeError("Chaining cycle detected for promise"));
        }
        // 如果x为promise 则采用其状态
        if (isPromise(x)) {
          if (x.state === "pending") {
            return x.then(()=> {
              resolve(x.value);
            }, () => {
              reject(x.reason);
            })
          }
          if (x.state === "fulfilled") {
            return resolve(x.value);
          }
          if (x.state === "rejected") {
            return reject(x.reason);
          }
        } else if (isObject(x) || isFunction(x)) {
          // 如果x是对象或者函数
          let then;
          // 取 x.then
          try {
            then = x.then;
          } catch (error) { // 取x.then 如果报错则直接失败
            reject(error);
          }
          // 如果 then 是 函数
          if (isFunction(then)) {
            // 只可以调用一个
            let isCalled = false;
            try {
              then.call(x, y => {
                if (isCalled) {
                  return;
                }
                isCalled = true;
                resolvePromise(promise2, y, resolve, reject);
              }, r => {
                if (isCalled) {
                  return;
                }
                isCalled = true;
                reject(r);
              })
            } catch (error) { // 执行then报错则直接返回失败
              if (isCalled) {
                return;
              }
              isCalled = true;
              reject(error);
            }
          } else { // 如果不是方法 则把x作为promsie的值
            resolve(x);
          }
        } else { // x 既不是方法也不是函数  则把x作为promsie的值
          resolve(x);
        }
      }
      // 辅助方法
      // 判断 obj 是不是 Function
      function isFunction(obj) {
        return !!obj && typeof obj === "function";
      }
      // 判断 obj 是不是 Object
      function isObject(obj) {
        return !!obj && typeof obj === "object";
      }
      // 判断 obj 是不是 Promise
      function isPromise(obj) {
        return !!obj && (typeof obj === "object" || typeof obj === "function") && typeof obj.then === "function";
      }
      
  1. catch 实现

    报错就走这个方法

      // catch 方法
      catch(fn) {
        return this.then(null, fn);
      }
    
  1. finall 实现

    不管成功还是失败,最后都要执行该方法,与 then不同

    参数:onFinally :Promise结束后调用的function

    返回值: 返回了一个设置了finally回调函数的Promise对象

    描述:如果你想在 promise 执行完毕后无论其结果怎样都做一些处理或清理时,finally() 方法可能是有用的。

    finally() 虽然与 .then(onFinally, onFinally) 类似,它们不同的是:

    • 调用内联函数时,不需要多次声明该函数或为该函数创建一个变量保存它。
    • 由于无法知道promise的最终状态,所以finally的回调函数中不接收任何参数,它仅用于无论最终结果如何都要执行的情况。
    • Promise.resolve(2).then(() => {}, () => {}) (resolved的结果为undefined)不同,Promise.resolve(2).finally(() => {}) resolved的结果为 2
    • 同样,Promise.reject(3).then(() => {}, () => {}) (resolved 的结果为undefined), Promise.reject(3).finally(() => {}) rejected 的结果为 3

    注意:finally回调中 throw(或返回被拒绝的promise)将以 throw() 指定的原因拒绝新的promise.

      // finall 方法
      finally(fn) {
        return new Promise((resolve, reject) => {
          try {
            fn();
          } catch (error) {
            reject(error);
          }
          if (this.state === "fulfilled") {
            resolve(this.value);
          }
          if (this.state === "rejected") {
            reject(this.reason);
          }
        })
      }
    
  1. Promise.resolve 实现

    Promise.resolve = (value) => {
      return new Promise((resolve, reject) => {
        resolve(value);
      });
    }
    
  1. Promise.reject 实现

    Promise.reject = (reason) => {
      return new Promise((resolve, reject) => {
        resolve(reason);
      });
    }
    
  1. Promise.all 实现

    all 方法

    • Promise.all([p1, p2, p3])用于将多个promise实例,包装成一个新的Promise实例,返回的实例就是普通的promise

    • 它接收一个数组作为参数

    • 数组里可以是Promise对象,也可以是别的值,只有Promise会等待状态改变

    • 当所有的子Promise都完成,该Promise完成,返回值是全部值得数组

    • 有任何一个失败,该Promise失败,返回值是第一个失败的子Promise结果

    Promise.all = (promiseArr) => {
      let result = [];
      let i = 0;
      function handleData(index, value, resolve) {
        result[index] = value;
        i++;
        if (i == promiseArr.length) {
          resolve(result);
        }
      }
      return new Promise((resolve, reject) => {
        for (let i = 0; i < promiseArr.length; i++) {
          if (isPromise(promiseArr[i])) {
            promiseArr[i].then(value => {
              handleData(i, value, resolve);
            }, reject)
          } else {
            handleData(i, promiseArr[i], resolve);
          }
        }
      })
    }
    
  1. Promise.allSettled 实现

    allSettled 方法

    • Promise.allSettled([p1, p2, p3])用于将多个promise实例,包装成一个新的Promise实例,返回的实例就是普通的promise

    • 它接收一个数组作为参数

    • 数组里是Promise对象

    • 当所有的子Promise都完成,该Promise完成,返回值是一个对象 包含每个子promise执行后得状态及对应得值或原因

    • 只要所有得子promise都执行完成,结果Promise为fulfilled状态

    Promise.allSettled = (promiseArr) => {
      let result = [];
      let i = 0;
      function handleData(index, data, resolve) {
        result[index] = data;
        i++;
        if (i == promiseArr.length) {
          resolve(result);
        }
      }
      return new promise((resolve, reject) => {
        for (let i = 0; i < promiseArr.length; i++) {
          promiseArr[i].then(value => {
            handleData(i, {state: "fulfilled", value: value}, resolve);
          }, error => {
            handleData(i, {state: "rejected", reason: error}, resolve);
          });
        }
      });
    }
    
  1. Promise.race 实现

    race 方法 有一个完成就算完成,返回的promise状态同第一个完成的

    Promise.race = (promiseArr) => {
      return new promise((resolve, reject) => {
        for (let i = 0; i < promiseArr.length; i++) {
          promiseArr[i].then(resolve, reject);
        }
      });
    }
    
  1. 完整代码

    class Promise {
      // 构造器
      constructor(executor) {
        // 状态 默认为 pending 状态
        this.state = "pending";
        // 成功的值
        this.value = undefined;
        // 失败的原因
        this.reason = undefined;
        // 成功存放方法的数组
        this.onResolvedCallbacks = [];
        // 失败存放方法的数组
        this.onRejectedCallbacks = [];
        // resolve(value) 将状态改为 fulfilled 状态
        let resolve = value => {
          this.value = value;
          this.state = "fulfilled";
          // 一旦 resolve 执行, 则按顺序 调用 成功数组 中的函数
          this.onResolvedCallbacks.forEach(fn => {
            fn();
          });
        }
        // reject(reason) 将状态改为 rejected 状态
        let reject = reason => {
          this.reason = reason;
          this.state = "rejected";
          // 一旦 reject 执行, 则按顺序 调用 失败数组 中的函数
          this.onRejectedCallbacks.forEach(fn => {
            fn();
          });
        }
        // 如果 executor 报错 立即执行 reject
        try{
          // 立即执行 executor 方法
          executor(resolve, reject);
        } catch(error) {
          reject(error);
        }
      }
      // then 方法
      then(onFulfilled, onRejected) {
        // onFulfilled 为可选参数 如果不为函数 则忽略onFulfilled 直接返回 value
        onFulfilled = isFunction(onFulfilled) ? onFulfilled : value => value;
        // onRejected 为可选参数 如果不为函数 则忽略onFulfilled 直接抛出错误
        onRejected = isFunction(onRejected) ? onRejected : error => { throw error};
        // 如果 Promise 为 成功状态 调用 onFulfilled 方法 传入成功的 value
        if(this.state === "fulfilled") {
          // 异步调用
          setTimeout(() => {
            try {
              let x = onFulfilled(this.value);
              resolvePromise(promise2, x, resolve, reject);
            } catch (error) {
              reject(error);
            }
          }, 0);
        }
        // 如果 Promise 为 失败状态 调用 onRejected 方法 传入失败的 reason
        if (this.state === "rejected") {
          // 异步调用
          setTimeout(() => {
            try {
              let x = onRejected(this.reason);
              resolvePromise(promise2, x, resolve, reject);
            } catch (error) {
              reject(error);
            }
          }, 0);
        }
        // 如果 Promise 为 等待状态 
        // 由于不知道 是成功还是失败,则需要两个数组,
        // 将成功或失败各自对应的方法 push 到各自的数组当中
        if (this.state === "pending") {
          // onFulfilled 传入到成功数组
          this.onResolvedCallbacks.push(() => {
            // 异步调用
            setTimeout(() => {
              try {
                let x = onFulfilled(this.value);
                resolvePromise(promise2, x, resolve, reject);
              } catch (error) {
                reject(error);
              }
            }, 0);
          });
          // onRejected 传入到成功的数组
          this.onRejectedCallbacks.push(() => {
            // 异步调用
            setTimeout(() => {
              try {
                let x = onRejected(this.reason);
                resolvePromise(promise2, x, resolve, reject);
              } catch (error) {
                reject(error);
              }
            }, 0);
          });
        }
      }
      // catch 方法
      catch(fn) {
        return this.then(null, fn);
      }
      // finall 方法
      finally(fn) {
        return new Promise((resolve, reject) => {
          try {
            fn();
          } catch (error) {
            reject(error);
          }
          if (this.state === "fulfilled") {
            resolve(this.value);
          }
          if (this.state === "rejected") {
            reject(this.reason);
          }
        })
      }
    }
    
    Promise.resolve = (value) => {
      return new Promise((resolve, reject) => {
        resolve(value);
      });
    }
    Promise.reject = (reason) => {
      return new Promise((resolve, reject) => {
        resolve(reason);
      });
    }
    Promise.all = (promiseArr) => {
      let result = [];
      let i = 0;
      function handleData(index, value, resolve) {
        result[index] = value;
        i++;
        if (i == promiseArr.length) {
          resolve(result);
        }
      }
      return new Promise((resolve, reject) => {
        for (let i = 0; i < promiseArr.length; i++) {
          if (isPromise(promiseArr[i])) {
            promiseArr[i].then(value => {
              handleData(i, value, resolve);
            }, reject)
          } else {
            handleData(i, promiseArr[i], resolve);
          }
        }
      })
    }
    Promise.allSettled = (promiseArr) => {
      let result = [];
      let i = 0;
      function handleData(index, data, resolve) {
        result[index] = data;
        i++;
        if (i == promiseArr.length) {
          resolve(result);
        }
      }
      return new promise((resolve, reject) => {
        for (let i = 0; i < promiseArr.length; i++) {
          promiseArr[i].then(value => {
            handleData(i, {state: "fulfilled", value: value}, resolve);
          }, error => {
            handleData(i, {state: "rejected", reason: error}, resolve);
          });
        }
      });
    }
    Promise.race = (promiseArr) => {
      return new promise((resolve, reject) => {
        for (let i = 0; i < promiseArr.length; i++) {
          promiseArr[i].then(resolve, reject);
        }
      });
    }
    
    function resolvePromise(promise2, x, resolve, reject) {
      // 如果 x 和 promise2 指向相同
      if (x === promise2) {
        reject(new TypeError("Chaining cycle detected for promise"));
      }
      // 如果x为promise 则采用其状态
      if (isPromise(x)) {
        if (x.state === "pending") {
          return x.then(()=> {
            resolve(x.value);
          }, () => {
            reject(x.reason);
          })
        }
        if (x.state === "fulfilled") {
          return resolve(x.value);
        }
        if (x.state === "rejected") {
          return reject(x.reason);
        }
      } else if (isObject(x) || isFunction(x)) {
        // 如果x是对象或者函数
        let then;
        // 取 x.then
        try {
          then = x.then;
        } catch (error) { // 取x.then 如果报错则直接失败
          reject(error);
        }
        // 如果 then 是 函数
        if (isFunction(then)) {
          // 只可以调用一个
          let isCalled = false;
          try {
            then.call(x, y => {
              if (isCalled) {
                return;
              }
              isCalled = true;
              resolvePromise(promise2, y, resolve, reject);
            }, r => {
              if (isCalled) {
                return;
              }
              isCalled = true;
              reject(r);
            })
          } catch (error) { // 执行then报错则直接返回失败
            if (isCalled) {
              return;
            }
            isCalled = true;
            reject(error);
          }
        } else { // 如果不是方法 则把x作为promsie的值
          resolve(x);
        }
      } else { // x 既不是方法也不是函数  则把x作为promsie的值
        resolve(x);
      }
    }
    // 辅助方法
    // 判断 obj 是不是 Function
    function isFunction(obj) {
      return !!obj && typeof obj === "function";
    }
    // 判断 obj 是不是 Object
    function isObject(obj) {
      return !!obj && typeof obj === "object";
    }
    // 判断 obj 是不是 Promise
    function isPromise(obj) {
      return !!obj && (typeof obj === "object" || typeof obj === "function") && typeof obj.then === "function";
    }
    
  1. 验证promise是否正确

    • 先在后面加上下述代码

    • npm 有一个promises-aplus-tests插件 npm i promises-aplus-tests -g 可以全局安装 mac用户最前面加上sudo

    • 命令行 promises-aplus-tests [js文件名] 即可验证

    // 目前是通过他测试 他会测试一个对象
    // 语法糖
    Promise.defer = Promise.deferred = function () {
      let dfd = {}
      dfd.promise = new Promise((resolve,reject)=>{
        dfd.resolve = resolve;
        dfd.reject = reject;
      });
      return dfd;
    }
    module.exports = Promise;
    //npm install promises-aplus-tests 用来测试自己的promise 符不符合promisesA+规范
    
    
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容