手写promise及方法

94 阅读1分钟
class MyPromise {
  constructor(fn) {
    this.state = "pending";
    this.result = null;
    this.onFulfilledCallbacks = [];
    this.onRejectedCallbacks = [];
    this.resolve = this.resolve.bind(this);
    this.reject = this.reject.bind(this);

    try {
      fn(this.resolve, this.reject);
    } catch (err) {
      throw Error(err);
    }
  }
  resolve(value) {
    // 保证状态不可逆
    if (this.state !== "pending") {
      return;
    }
    this.state = "fulfilled";
    this.result = value;
    // 处理resolve函数里是异步函数,在then里收集,这里执行
    while (this.onFulfilledCallbacks.length) {
      this.onFulfilledCallbacks.shift()();
    }
  }
  reject(value) {
    if (this.state !== "pending") {
      return;
    }
    this.state = "rejected";
    this.result = value;

    while (this.onRejectedCallbacks.length) {
      this.onRejectedCallbacks.shift()();
    }
  }
  then(onFulfilled, onRejected) {
    // 处理这两种情况 .then(200) 和.then((resp) => resp)
    onFulfilled =
      typeof onFulfilled === "function" ? onFulfilled : (val) => val;
    onRejected =
      typeof onRejected === "function"
        ? onRejected
        : (reason) => {
            throw Error(reason);
          };

    // 解决链式调用问题
    var thenPromise = new MyPromise((resolve, reject) => {
      const handlePromise = (cb) => {
        // 考虑到这里是微任务,需要比同步任务晚执行,所以用settimeout包一下
        setTimeout(() => {
          try {
            const result = cb(this.result);
            if (result === thenPromise) {
              throw Error("不能是自己");
            }

            if (result instanceof MyPromise) {
              result.then(resolve, reject);
            } else {
              resolve(resolve);
            }
          } catch (err) {
            reject(err);
            throw Error(err);
          }
        });
      };
      if (this.state === "fulfilled") {
        //   onFulfilled(this.result);
        handlePromise(onFulfilled);
      } else if (this.state === "rejected") {
        //   onRejected(this.result);
        handlePromise(onRejected);
      } else {
        this.onFulfilledCallbacks.push(handlePromise(onFulfilled));
        this.onRejectedCallbacks.push(handlePromise(onRejected));
      }
    });

    return thenPromise;
  }
}

原型上的方法


// promise的方法 all、race、any、allsettled
// all所有结果返回才resolve,有一个reject就reject

const all = (promiseList) => {
  const result = [];
  let count = 0;

  return new Promise((resolve, reject) => {
    const addData = (res, index) => {
      result[index] = res;
      count++;
      if (count === promiseList.length) {
        resolve(result);
      }
    };
    promiseList.forEach((p, index) => {
      if (p instanceof Promise) {
        p.then((res) => {
          addData(res, index);
        }).catch((err) => {
          reject(err);
        });
      } else {
        addData(p, index);
      }
    });
  });
};

// race 获得最先返回的那个结果
const race = (promiseList) => {
  return new Promise((resolve, reject) => {
    promiseList.forEach((p) => {
      if (p instanceof Promise) {
        p.then((resp) => {
          resolve(resp);
        }).catch((err) => {
          reject(err);
        });
      } else {
        resolve(p);
      }
    });
  });
};

// any 任何一个成功 就成功,其全部失败就是失败

const any = (promiseList) => {
  let count = 0;
  return new Promise((resolve, reject) => {
    promiseList.forEach((p) => {
      if (p instanceof Promise) {
        p.then((resp) => {
          resolve(resp);
        }).catch((err) => {
          count++;
          if (count === promiseList.length) {
            reject(err);
          }
        });
      } else {
        resolve(resp);
      }
    });
  });
};

// allsettled 等待所有结果返回 记录status和value, 不会因为其中一个rejected而终止,会继续等待其他的
const allsettled = (promiseList) => {
  const result = [];
  let count = 0;
  return new Promise((resolve, reject) => {
    const addData = (value, status, i) => {
      result[i] = {
        status,
        value,
      };
      count++;
      if (count === promiseList.length) {
        resolve(result);
      }
    };
    promiseList.forEach((p, index) => {
      if (p instanceof Promise) {
        p.then((resp) => {
          addData(resp, "fulfilled", index);
        }).catch((err) => {
          addData(resp, "rejected", index);
        });
      } else {
        addData(p, "fulfilled", index);
      }
    });
  });
};