美文网首页
使用Promise/A+ 规范,实现Promise

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

作者: 带刀打天下 | 来源:发表于2020-11-16 10:08 被阅读0次

    一、规范简介

    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+规范
      
      

    相关文章

      网友评论

          本文标题:使用Promise/A+ 规范,实现Promise

          本文链接:https://www.haomeiwen.com/subject/rieabktx.html