Promise/A+规范实现

8 篇文章 0 订阅

实现:

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

/* MyPromise 的状态 */
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";
/* 规范中的resolvePromise(promise2, x) 规定 */

// 1、如果promise和x指向相同的对象,会导致循环调用,直接返回失败
// 2、如果x是一个promise:查看x的状态 pending 则需等待状态改变,fulfilled value 为 promise的值 ,reject reason为promise的reason
// 3、如果x是一个对象或一个函数: 执行x的then方法
//    3.1、如果 没有x.then 则直接返回失败
//    3.2、如果 有x.then 且为函数,则执行 then.call(),参数:x 作为this,成功时的回调,失败时的回调。
//        3.2.1、如果成功的回调还是promise,值为y,再次调用 resolvePromise(promise2, y, resolve, reject)
//        3.2.2、如果失败,则执行失败回到,原因为r,直接返回失败
//        3.2.3、成功和失败只能调用一个,所以设定一个isCalled来防止多次调用
//    3.3、如果 有x.then但不是函数,则将x作为promise的值
// 4、如果x不是对象也不是函数:把x作为promise的值,设置成fulfilled状态

const resolvePromise = (promise2, x, resolve, reject) => {
  // A+规范中  x和promise2引用同一个对象抛出类型错误
  if (promise2 === x) {
    return reject(
      new TypeError("Chaining cycle detected for MyPromise #<MyPromise>")
    );
  }
  // 只可以调用一个
  let isUsed;
  // 后续的条件要严格判断   保证代码能和别的库一起使用
  // x可能是一个函数或者对象
  if (x instanceof MyPromise) {
    // 判断 x 为 MyPromise
    x.then(
      (value) => {
        resolvePromise(promise2, value, resolve, reject);
      },
      (reason) => {
        reject(reason);
      }
    );
  } else if (x !== null && (typeof x === "object" || typeof x === "function")) {
    // x 为对象或函数
    try {
      let then = x.then;
      if (typeof then === "function") {
        // 只能判断then是函数就认为其是promise
        then.call(
          x,
          (y) => {
            if (isUsed) return;
            isUsed = true;
            resolvePromise(promise2, y, resolve, reject);
          },
          (e) => {
            if (isUsed) return;
            isUsed = true;
            reject(e);
          }
        );
      } else {
        if (isUsed) return;
        isUsed = true;
        resolve(x);
      }
    } catch (e) {
      if (isUsed) return;
      isUsed = true;
      reject(e);
    }
  } else {
    //返回的基本类型,直接resolve
    resolve(x);
  }
};

// 定义一个 class
class MyPromise {
  //  ========>A+规范:传入一个参数(函数),该函数为立即执行函数,这里面我们起名为 executor
  constructor(executor) {
    if (typeof executor !== "function") {
      throw new TypeError(`MyPromise resolver ${executor} is not a function`);
    }
    // 初始状态
    this.state = PENDING;
    // 成功返回值
    this.value = undefined;
    // 失败返回值
    this.reason = undefined;
    // 成功存放方法的数组
    this.onResolvedCallbacks = [];
    // 失败存放方法的数组
    this.onRejectedCallbacks = [];
    // resolve函数,将状态更改为FULFILLED
    let resolve = (value) => {
      this.state = FULFILLED;
      this.value = value;
      // 一旦 resolve 执行, 则按顺序 调用 成功数组 中的函数
      this.onResolvedCallbacks.forEach((fn) => fn());
    };
    // inject函数,将状态更改为REJECTED
    let inject = (reason) => {
      this.state = REJECTED;
      this.reason = reason;
      // 一旦 reject 执行, 则按顺序 调用 失败数组 中的函数
      this.onRejectedCallbacks.forEach((fn) => fn());
    };
    //  如果 executor 报错 立即执行 reject
    try {
      // 立即执行函数
      //  ========>A+规范:executor 函数接收两个参数,resolve 与 reject,成功时resolve(value),失败时reject(reason)。
      executor(resolve, inject);
    } catch (error) {
      inject(error);
    }
  }
  /* ========>A+规范: 一个 MyPromise 必须提供 then 方法,访问其当前或最终value或reason */
  // then 方法必须返回一个Promise
  // 如果 onFulfilled 或 onRejected 执行时报错,则直接返回失败
  // onFulfilled 不是函数,promise1的状态是fulfilled :这时 promise2的状态是fulfilled,值同promise1
  // onRejected 不是函数,promise1 的状态是 rejected:这时promise2的状态是 rejected,拒绝原因 reason 同promise1
  // 如果一个 onFulfilled 或 onRejected 返回一个值 x(自己return x),则需要对x进行处理,处理的函数叫做:resolvePromise(promise2, x)

  // 1: MyPromise 成功或者失败会传递到外层的下一个then方法
  // 2: 返回的是普通值(除了promise之外的值)都会触底到下一then的成功中;出错的情况走到下一次的失败中;
  // 3: 错误处理 。自己最近的then没有错误处理,会向下传递错误直到有错误处理
  // 4: 每次执行完then 返回都是新的promise (一旦成功或者失败就不能够修改状态)
  then(onFulfilled, onRejected) {
    // // onFulfilled 为可选参数 如果不为函数 则忽略onFulfilled 直接返回 value
    // typeof onFulfilled === "function" ? onFulfilled : (value) => value;
    // // onRejected 为可选参数 如果不为函数 则忽略onFulfilled 直接抛出错误
    // typeof onRejected === "function"
    //   ? onRejected
    //   : (error) => {
    //       throw error;
    //     };
    //  链式调用
    let promise2 = new MyPromise((resolve, inject) => {
      if (this.state === FULFILLED) {
        setTimeout(() => {
          try {
            // 如果状态是成功了,需要调用传入的第一个onFulfilled函数
            //成功的回调直接执行;执行完成后拿到结果;ps: 成功之后返回的直接执行拿到结果存放到x中
            // 但是返回的promise 还能继续then,继续传递成功的结果
            let x = onFulfilled(this.value);
            // x可能是promise,解析promise ,使用这个返回的结果决定下一个then是成功还是失败
            resolvePromise(promise2, x, resolve, inject); // 调用了下一个promise的resolve
          } catch (error) {
            inject(error);
          }
        }, 0);
      }
      if (this.state === REJECTED) {
        setTimeout(() => {
          try {
            // 如果状态失败了,就需要使用第二个函数讲失败的原因返回
            let x = onRejected(this.reason);
            // 处理失败
            resolvePromise(promise2, x, resolve, inject); //普通值都会传递到下一个的成功
          } catch (error) {
            inject(error);
          }
        }, 0);
      }
      if (this.state === PENDING) {
        this.onResolvedCallbacks.push(() => {
          // todo
          setTimeout(() => {
            try {
              let x = onFulfilled(this.value);
              resolvePromise(promise2, x, resolve, inject);
            } catch (error) {
              inject(error);
            }
          }, 0);
        });
        this.onRejectedCallbacks.push(() => {
          // todo
          setTimeout(() => {
            try {
              let x = onRejected(this.reason);
              resolvePromise(promise2, x, resolve, inject);
            } catch (error) {
              inject(error);
            }
          }, 0);
        });
      }
    });
    // 返回promise,完成链式
    return promise2;
  }
  // catch 方法
  catch(errCallBack) {
    return this.then(null, errCallBack);
  }
  static resolve(data) {
    // 快速创建一个成功的promise
    return new MyPromise((resolve, reject) => {
      resolve(data);
    });
  }
  static reject(reason) {
    // 快速创建一个失败的promise
    return new MyPromise((resolve, reject) => {
      reject(reason);
    });
  }
  static all(promiseArr) {
    let result = [];
    let i = 0;
    return new MyPromise((resolve, reject) => {
      for (let i = 0; i < promiseArr.length; i++) {
        if (isPromise(promiseArr[i])) {
          promiseArr[i].then((data) => {
            result[i] = data;
            if (result.length === promiseArr.length) {
              resolve(result);
            }
          }, reject);
        } else {
          result[i] = promiseArr[i];
        }
      }
    });
  }
  static race(promiseArr) {
    return new MyPromise((resolve, reject) => {
      for (let i = 0; i < promiseArr.length; i++) {
        promiseArr[i].then(resolve, reject);
      }
    });
  }
  static finally(fn) {
    return new MyPromise((resolve, reject) => {
      try {
        fn();
      } catch (error) {
        reject(error);
      }
      if (this.state === "fulfilled") {
        resolve(this.value);
      }
      if (this.state === "rejected") {
        reject(this.reason);
      }
    });
  }
}
function isPromise(obj) {
  return (
    !!obj &&
    (typeof obj === "object" || typeof obj === "function") &&
    typeof obj.then === "function"
  );
}
module.exports = MyPromise;

测试:

const MyPromise = require("./Promise.js");

let p = new MyPromise((resolve, inject) => {
  console.log("1111111");
  resolve("数据1");
});

p.then(
  (res) => {
    console.log("第一次then res");
    console.log(res);
    return res;
  },
  (error) => {
    console.log("第一次then error");
    console.log(error);
  }
)
  .then(
    (res) => {
      console.log("第二次then res");
      console.log(res);
      return new MyPromise((resolve, reject) => {
        setTimeout(() => {
          resolve(res);
          // reject(res);
        }, 100);
      });
    },
    (error) => {
      console.log("第二次then error");
      console.log(error);
    }
  )
  .then(
    (res) => {
      console.log("第三次then res");
      console.log(res);
      return res;
    },
    (err) => {
      console.log("第三次then error");
      console.log(err);
      return "error";
    }
  )
  .catch((data) => {
    console.log(data);
  });

结果:

1111111
第一次then res
数据1
第二次then res
数据1
第三次then res
数据1
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值