JavaScript异步编程规范->实现一个符合Promise A+规范的 Promise

🎉 博客主页:【剑九 六千里-CSDN博客
🎠 系列专栏:【面试题-八股系列
💖 感谢大家点赞👍收藏⭐评论✍

在这里插入图片描述


1.Promise基本使用

  • Promise 是一个构造函数
  • 通过 new 创建
  • 接收一个拥有 resolvereject 两个参数的 callback
let p1 = new Promise((resolve, reject) => {});
console.log("p1", p1);

let p2 = new Promise((resolve, reject) => {
  resolve("success");
  reject("error");
});
console.log("p2", p2);

let p3 = new Promise((resolve, reject) => {
  reject("error");
  resolve("success");
});
console.log("p3", p3);

let p4 = new Promise((resolve, reject) => {
  throw "报错啦~";
});
console.log("p4", p4);

这里说明了 Promise 的五个特点:

  1. 初始化的时候,Promise状态为pending
  2. 执行了resolvePromise状态会变成fulfilled
  3. 执行了rejectPromise状态会变成rejected
  4. Promise状态不可逆,第一次成功就永久为fulfilled,第一次失败就永远状态为rejected
  5. Promise中有throw的话,就相当于执行了reject

在这里插入图片描述

2.实现一个Promise

2.1.resolve/reject

2.1.1.初始化状态及返回值

  • 初始状态为 pending
class myPromise {
  constructor(exector) {
    // 初始化状态及初始值
    this.initValue();
  }
  initValue() {
    this.PromiseState = "pending"; // Promise 状态
    this.PromiseResult = undefined; // Promise 返回值
  }
}

在这里插入图片描述

2.1.2.实现resolve/reject

  • new 的时候接收 resolvereject,并修改状态
class myPromise {
  constructor(exector) {
    // 初始化状态及初始值
    this.initValue();
    // 执行器,当 new MyPromise()时,这个callback要接受 resolve 和 reject 函数
    exector(this.resolve, this.reject);
  }
  initValue() {
    this.PromiseState = "pending"; // Promise 状态
    this.PromiseResult = undefined; // Promise 返回值
  }
  resolve(value) {
    // 此时状态改为 fulfilled
    this.PromiseState = "fulfilled";
    // 将传递进来的参数赋值
    this.PromiseResult = value;
  }
  reject(reason) {
    // 此时状态改为 rejected
    this.PromiseState = "rejected";
    // 将传递进来的错误抛出
    this.PromiseResult = reason;
  }
}

测试:

let test = new myPromise((resolve, reject) => {
  resolve("成功啦~");
  reject("失败啦~");
});
console.log(test);

此时发现报错了,经过排查原因发现是 this 指向问题,当 new MyPromise 创建实例对象后,此时 test 上还没有绑定 resolve和reject方法;
在这里插入图片描述

增加一个 initBind 方法,用于初始化时将 this 绑定到实例对象上:

class myPromise {
  constructor(exector) {
    // 初始化状态及初始值
    this.initValue();
    // 初始化的时候改变 this 指向,将 this 指向实例对象
    this.initBind();
    // 执行器,当 new MyPromise()时,这个callback要接受 resolve 和 reject 函数
    exector(this.resolve, this.reject);
  }
  initValue() {
    this.PromiseState = "pending"; // Promise 状态
    this.PromiseResult = undefined; // Promise 返回值
  }
  initBind() {
    this.resolve = this.resolve.bind(this);
    this.reject = this.reject.bind(this);
  }
  resolve(value) {
    // 此时状态改为 fulfilled
    this.PromiseState = "fulfilled";
    // 将传递进来的参数赋值
    this.PromiseResult = value;
  }
  reject(reason) {
    // 此时状态改为 rejected
    this.PromiseState = "rejected";
    // 将传递进来的错误抛出
    this.PromiseResult = reason;
  }
}

let test = new myPromise((resolve, reject) => {
  resolve("成功啦~");
  reject("失败啦~");
});
console.log(test);

测试:

let test = new myPromise((resolve, reject) => {
  resolve("成功啦~");
  reject("失败啦~");
});

此时已经可以正常执行了:

在这里插入图片描述

2.1.3.状态不可逆

我们知道原生的 Promise 状态是不可逆的,只能改变一次,预期只执行 resolve, 但是这里也执行了 reject,改造如下:

class myPromise {
  constructor(exector) {
    // 初始化状态及初始值
    this.initValue();
    // 初始化的时候改变 this 指向,将 this 指向实例对象
    this.initBind();
    // 执行器,当 new MyPromise()时,这个callback要接受 resolve 和 reject 函数
    exector(this.resolve, this.reject);
  }
  initValue() {
    this.PromiseState = "pending"; // Promise 状态
    this.PromiseResult = undefined; // Promise 返回值
  }
  initBind() {
    this.resolve = this.resolve.bind(this);
    this.reject = this.reject.bind(this);
  }
  resolve(value) {
    // 只要状态已经改变,就不允许继续修改状态
    if (this.PromiseState !== "pending") {
      return;
    }
    // 此时状态改为 fulfilled
    this.PromiseState = "fulfilled";
    // 将传递进来的参数赋值
    this.PromiseResult = value;
  }
  reject(reason) {
    // 只要状态已经改变,就不允许继续修改状态
    if (this.PromiseState !== "pending") {
      return;
    }
    // 此时状态改为 rejected
    this.PromiseState = "rejected";
    // 将传递进来的错误抛出
    this.PromiseResult = reason;
  }
}

测试:

let test1 = new myPromise((resolve, reject) => {
  resolve("成功啦test1~");
  reject("失败啦test1~");
});
console.log(test1);

let test2 = new myPromise((resolve, reject) => {
  reject("失败啦test2~");
  resolve("成功啦test2~");
});
console.log(test2);

此时状态已不可逆:

在这里插入图片描述

2.1.4.处理throw

此时如果直接抛出错误,会怎么样呢?

let test3 = new myPromise((resolve, reject) => {
  throw "报错啦test3~";
});
console.log(test3);

由原生 Promise 可以知道,如果直接抛出错误,那么状态和 reject 执行时一样,都是 rejected ,此时不满足预期的功能:

在这里插入图片描述
继续改造,增加 try catch 来处理异常:

class myPromise {
  constructor(exector) {
    // 初始化状态及初始值
    this.initValue();
    // 初始化的时候改变 this 指向,将 this 指向实例对象
    this.initBind();
    // 执行器,当 new MyPromise()时,这个callback要接受 resolve 和 reject 函数
    try {
      // 正常执行的话,执行 exector
      exector(this.resolve, this.reject);
    } catch(err) {
      // 捕获到异常,则执行一次 reject
      this.reject(err);
    }
  }
  initValue() {
    this.PromiseState = "pending"; // Promise 状态
    this.PromiseResult = undefined; // Promise 返回值
  }
  initBind() {
    this.resolve = this.resolve.bind(this);
    this.reject = this.reject.bind(this);
  }
  resolve(value) {
    // 只要状态已经改变,就不允许继续修改状态
    if (this.PromiseState !== "pending") {
      return;
    }
    // 此时状态改为 fulfilled
    this.PromiseState = "fulfilled";
    // 将传递进来的参数赋值
    this.PromiseResult = value;
  }
  reject(reason) {
    // 只要状态已经改变,就不允许继续修改状态
    if (this.PromiseState !== "pending") {
      return;
    }
    // 此时状态改为 rejected
    this.PromiseState = "rejected";
    // 将残敌进来的错误抛出
    this.PromiseResult = reason;
  }
}

测试:

let test3 = new myPromise((resolve, reject) => {
  throw "报错啦test3~";
});
console.log(test3);

此时已经满足了预期的功能:

在这里插入图片描述

2.2.then

平时业务中then的使用一般如下:

// 马上输出 -> "成功了"
const p1 = new Promise((resolve, reject) => {
  resolve("成功了"); // 成功的话,执行 then 中的成功回调
}).then(
  (res) => console.log(res),
  (err) => console.log(err)
);

// 1秒后输出 -> "失败了"
const p2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject("失败了"); // 失败的话执行 then 中的失败回调
  }, 1000);
}).then(
  (res) => console.log(res),
  (err) => console.log(err)
);

// 链式调用 -> 输出 200
const p3 = new Promise((resolve, reject) => {
  resolve(100); // 成功的话执行 then 中成功的回调
})
  .then(
    (res) => 2 * res,
    (err) => console.log(err)
  )
  .then(
    (res) => console.log(res),
    (err) => console.log(err)
  );

总结 then 的使用规则:

  1. then 接收两个参数,一个是成功回调,一个是失败回调;
  2. 状态为 fulfilled 时执行成功回调,状态为 rejected 时执行失败回调;
  3. resolvereject 可以在定时器中,并且定时器时间结束后依次执行
  4. then 可以链式调用,上一次 then 的返回值传递给下一个 then

2.2.1.实现then

根据上面总结的规则,声明一个 then 函数:

class myPromise {
  constructor(exector) {
    // 初始化状态及初始值
    this.initValue();
    // 初始化的时候改变 this 指向,将 this 指向实例对象
    this.initBind();
    // 执行器,当 new MyPromise()时,这个callback要接受 resolve 和 reject 函数
    try {
      // 正常执行的话,执行 exector
      exector(this.resolve, this.reject);
    } catch(err) {
      // 捕获到异常,则执行一次 reject
      this.reject(err);
    }
  }
  initValue() {
    this.PromiseState = "pending"; // Promise 状态
    this.PromiseResult = undefined; // Promise 返回值
  }
  initBind() {
    this.resolve = this.resolve.bind(this);
    this.reject = this.reject.bind(this);
  }
  resolve(value) {
    // 只要状态已经改变,就不允许继续修改状态
    if (this.PromiseState !== "pending") {
      return;
    }
    // 此时状态改为 fulfilled
    this.PromiseState = "fulfilled";
    // 将传递进来的参数赋值
    this.PromiseResult = value;
  }
  reject(reason) {
    // 只要状态已经改变,就不允许继续修改状态
    if (this.PromiseState !== "pending") {
      return;
    }
    // 此时状态改为 rejected
    this.PromiseState = "rejected";
    // 将残敌进来的错误抛出
    this.PromiseResult = reason;
  }
  then(onFulfilled, onRejected) {
    // then 函数接收两个callback,一个是成功回调,一个是失败回调
    // 参数兜底处理,确保返回的都是回调函数
    onFulfilled = typeof onFulfilled === "function" ? onFulfilled : (value) => value;
    onRejected = typeof onRejected === "function"
        ? onRejected
        : (reason) => {
            throw reason;
          };

    // 如果成功,则执行成功回调
    // 如果失败,则执行失败回调
    if (this.PromiseState === "fulfilled") {
      onFulfilled(this.PromiseResult);
    } else if (this.PromiseState === "rejected") {
      onRejected(this.PromiseResult);
    }
  }
}

测试:

let test1 = new myPromise((resolve, reject) => {
  resolve(10);
}).then(
  (res) => console.log(res),
  (err) => console.log(err)
);

then 的基本功能已实现:

在这里插入图片描述

2.2.2.通过队列实现setTimeout

下面的代码如何按预期的 1s 之后再执行呢?

// 1秒后输出 ”fail“
const p2 = new Promise((resolve, reject) => {
    setTimeout(() => {
        reject('fail')
    }, 1000)
}).then(res => console.log(res), err => console.log(err))
  1. 我们不能保证 1s 之后才执行 then ,但是换个思路我们可以保证 then 中的回调,1s之后再执行;
  2. 在这 1s 中,可以先把 then 中的回调报错起来,等 resolve 或者 reject 执行之后,再去执行保存的回调函数。
  3. 只要执行 resolve 或者 reject 那么状态就会发生变化,只需要在状态为 pending 时使用一个数组将回调保存起来即可:
class myPromise {
  constructor(exector) {
    // 初始化状态及初始值
    this.initValue();
    // 初始化的时候改变 this 指向,将 this 指向实例对象
    this.initBind();
    // 执行器,当 new MyPromise()时,这个callback要接受 resolve 和 reject 函数
    try {
      // 正常执行的话,执行 exector
      exector(this.resolve, this.reject);
    } catch(err) {
      // 捕获到异常,则执行一次 reject
      this.reject(err);
    }
  }
  initValue() {
    this.PromiseState = "pending"; // Promise 状态
    this.PromiseResult = undefined; // Promise 返回值
    this.onFulfilledCallbacks = []; // 保存成功的回调
    this.onRejectedCallbacks = []; // 保存失败的回调
  }
  initBind() {
    this.resolve = this.resolve.bind(this);
    this.reject = this.reject.bind(this);
  }
  resolve(value) {
    // 只要状态已经改变,就不允许继续修改状态
    if (this.PromiseState !== "pending") {
      return;
    }
    // 此时状态改为 fulfilled
    this.PromiseState = "fulfilled";
    // 将传递进来的参数赋值
    this.PromiseResult = value;
    // 执行成功的回调
    while (this.onFulfilledCallbacks.length) {
      // 每次从队列中取出一个来执行
      this.onFulfilledCallbacks.shift()(this.PromiseResult);
    }
  }
  reject(reason) {
    // 只要状态已经改变,就不允许继续修改状态
    if (this.PromiseState !== "pending") {
      return;
    }
    // 此时状态改为 rejected
    this.PromiseState = "rejected";
    // 将传递进来的错误抛出
    this.PromiseResult = reason;
    // 执行成功的回调
    while (this.onRejectedCallbacks.length) {
      // 每次从队列中取出一个来执行
      this.onRejectedCallbacks.shift()(this.PromiseResult);
    }
  }
  then(onFulfilled, onRejected) {
    // then 函数接收两个callback,一个是成功回调,一个是失败回调
    // 参数兜底处理,确保返回的都是回调函数
    onFulfilled =
      typeof onFulfilled === "function" ? onFulfilled : (value) => value;
    onRejected =
      typeof onRejected === "function"
        ? onRejected
        : (reason) => {
            throw reason;
          };

    // 如果成功,则执行成功回调
    // 如果失败,则执行失败回调
    if (this.PromiseState === "fulfilled") {
      onFulfilled(this.PromiseResult);
    } else if (this.PromiseState === "rejected") {
      onRejected(this.PromiseResult);
    } else if (this.PromiseState === "pending") {
      // 将成功回调放入队列
      this.onFulfilledCallbacks.push(onFulfilled);
      // 将失败回调放入队列
      this.onRejectedCallbacks.push(onRejected);
    }
  }
}

测试:

let test1 = new myPromise((resolve, reject) => {
  setTimeout(() => {
    resolve("成功回调test1");
  }, 1000);
}).then(
  (res) => console.log(res),
  (err) => console.log(err)
);
let test2 = new myPromise((resolve, reject) => {
  setTimeout(() => {
    reject("失败回调test2");
  }, 2000);
}).then(
  (res) => console.log(res),
  (err) => console.log(err)
);

1s 之后执行成功回调,2s 之后执行失败回调,此时是满足预期的:

在这里插入图片描述

2.2.3.链式调用

此时还有一个问题,原生 Promise 是支持链式调用的,并且上一次 then 的值会传递给下一次 then,如下面这个例子:

// 链式调用 输出 200
const p3 = new Promise((resolve, reject) => {
  resolve(100)
}).then(res => 2 * res, err => console.log(err))
  .then(res => console.log(res), err => console.log(err))

// 链式调用 输出300
const p4 = new Promise((resolve, reject) => {
  resolve(100)
}).then(res => new Promise((resolve, reject) => resolve(3 * res)), err => console.log(err))
  .then(res => console.log(res), err => console.log(err))

MyPromise 目前还不支持。
为什么 Promise 能支持链式调用呢?
因为在 then 方法执行完成之后,返回值被包装成了一个 Promise

  1. then 方法本身会返回一个新的 Promise 对象;
  2. 如果返回值是 promise 对象,返回值为成功,新 promise 就是成功;
  3. 如果返回值是 promise 对象,返回值为失败,新 promise 就是失败;
  4. 如果返回值非 promise 对象,新 promise 对象就是成功,值为此返回值;

改造 MyPromise

class MyPromise {
  constructor(exector) {
    // 初始化状态及初始值
    this.initValue();
    // 初始化的时候改变 this 指向,将 this 指向实例对象
    this.initBind();
    // 执行器,当 new MyPromise()时,这个callback要接受 resolve 和 reject 函数
    try {
      // 正常执行的话,执行 exector
      exector(this.resolve, this.reject);
    } catch (err) {
      // 补货到异常,则执行一次 reject
      this.reject(err);
    }
  }
  initValue() {
    this.PromiseState = "pending"; // Promise 状态
    this.PromiseResult = undefined; // Promise 返回值
    this.onFulfilledCallbacks = []; // 保存成功的回调
    this.onRejectedCallbacks = []; // 保存失败的回调
  }
  initBind() {
    this.resolve = this.resolve.bind(this);
    this.reject = this.reject.bind(this);
  }
  resolve(value) {
    // 只要状态已经改变,就不允许继续修改状态
    if (this.PromiseState !== "pending") {
      return;
    }
    // 此时状态改为 fulfilled
    this.PromiseState = "fulfilled";
    // 将传递进来的参数赋值
    this.PromiseResult = value;
    // 执行成功的回调
    while (this.onFulfilledCallbacks.length) {
      // 每次从队列中取出一个来执行
      this.onFulfilledCallbacks.shift()(this.PromiseResult);
    }
  }
  reject(reason) {
    // 只要状态已经改变,就不允许继续修改状态
    if (this.PromiseState !== "pending") {
      return;
    }
    // 此时状态改为 rejected
    this.PromiseState = "rejected";
    // 将传递进来的错误抛出
    this.PromiseResult = reason;
    // 执行成功的回调
    while (this.onRejectedCallbacks.length) {
      // 每次从队列中取出一个来执行
      this.onRejectedCallbacks.shift()(this.PromiseResult);
    }
  }
  then(onFulfilled, onRejected) {
    // then 函数接收两个callback,一个是成功回调,一个是失败回调
    // 参数兜底处理,确保返回的都是回调函数
    onFulfilled =
      typeof onFulfilled === "function" ? onFulfilled : (value) => value;
    onRejected =
      typeof onRejected === "function"
        ? onRejected
        : (reason) => {
            throw reason;
          };
    var promiseThen = new MyPromise((resolve, reject) => {
      const handlePromise = (fn) => {
        try {
        let f = fn(this.PromiseResult);
          if (f === promiseThen) {
            // 不能返回自身
            throw new Error("不能返回自身。。。");
          }
          if (f instanceof MyPromise) {
            // 如果是 Promise 则执行对应的回调
            f.then(resolve, reject);
          } else {
            // 如果不是 Promise 则直接成功
            resolve(f);
          }
        } catch (error) {
          // 处理报错, 预防一些边界情况
          reject(error);
          throw new Error(error);
        }
      };
      // 如果成功,则执行成功回调
      // 如果失败,则执行失败回调
      if (this.PromiseState === "fulfilled") {
        // onFulfilled(this.PromiseResult);
        handlePromise(onFulfilled);
      } else if (this.PromiseState === "rejected") {
        // onRejected(this.PromiseResult);
        handlePromise(onRejected);
      } else if (this.PromiseState === "pending") {
        // 将成功回调放入队列
        this.onFulfilledCallbacks.push(handlePromise(onFulfilled));
        // 将失败回调放入队列
        this.onRejectedCallbacks.push(handlePromise(onRejected));
      }
    });

    // 返回包装的 Promise
    return promiseThen;
  }
}

测试:

const test1 = new MyPromise((resolve, reject) => {
  resolve(100);
})
  .then(
    (res) => 2 * res,
    (err) => 3 * err
  )
  .then(
    (res) => console.log("success", res),
    (err) => console.log("fail", err)
  );

const test2 = new MyPromise((resolve, reject) => {
  resolve(100);
})
  .then(
    (res) => new MyPromise((resolve, reject) => reject(2 * res)),
    (err) => new Promise((resolve, reject) => resolve(3 * err))
  )
  .then(
    (res) => console.log("success", res),
    (err) => console.log("fail", err)
  );

在这里插入图片描述

2.2.4.执行顺序

then 是微任务,因此执行会晚于全局上下文,例如:

const p = new Promise((resolve, reject) => {
    resolve(1)
}).then(res => console.log(res), err => console.log(err))

console.log(2)

// 输出顺序是 2 1

在我们的 MyPromise 中暂未实现该功能,此处可以通过 setTimeout 宏任务来将 then 异步执行:

class MyPromise {
  constructor(exector) {
    // 初始化状态及初始值
    this.initValue();
    // 初始化的时候改变 this 指向,将 this 指向实例对象
    this.initBind();
    // 执行器,当 new MyPromise()时,这个callback要接受 resolve 和 reject 函数
    try {
      // 正常执行的话,执行 exector
      exector(this.resolve, this.reject);
    } catch (err) {
      // 补货到异常,则执行一次 reject
      this.reject(err);
    }
  }
  initValue() {
    this.PromiseState = "pending"; // Promise 状态
    this.PromiseResult = undefined; // Promise 返回值
    this.onFulfilledCallbacks = []; // 保存成功的回调
    this.onRejectedCallbacks = []; // 保存失败的回调
  }
  initBind() {
    this.resolve = this.resolve.bind(this);
    this.reject = this.reject.bind(this);
  }
  resolve(value) {
    // 只要状态已经改变,就不允许继续修改状态
    if (this.PromiseState !== "pending") {
      return;
    }
    // 此时状态改为 fulfilled
    this.PromiseState = "fulfilled";
    // 将传递进来的参数赋值
    this.PromiseResult = value;
    // 执行成功的回调
    while (this.onFulfilledCallbacks.length) {
      // 每次从队列中取出一个来执行
      this.onFulfilledCallbacks.shift()(this.PromiseResult);
    }
  }
  reject(reason) {
    // 只要状态已经改变,就不允许继续修改状态
    if (this.PromiseState !== "pending") {
      return;
    }
    // 此时状态改为 rejected
    this.PromiseState = "rejected";
    // 将残敌进来的错误抛出
    this.PromiseResult = reason;
    // 执行成功的回调
    while (this.onRejectedCallbacks.length) {
      // 每次从队列中取出一个来执行
      this.onRejectedCallbacks.shift()(this.PromiseResult);
    }
  }
  then(onFulfilled, onRejected) {
    // then 函数接收两个callback,一个是成功回调,一个是失败回调
    // 参数兜底处理,确保返回的都是回调函数
    onFulfilled =
      typeof onFulfilled === "function" ? onFulfilled : (value) => value;
    onRejected =
      typeof onRejected === "function"
        ? onRejected
        : (reason) => {
            throw reason;
          };
    var promiseThen = new MyPromise((resolve, reject) => {
      const handlePromise = (fn) => {
        setTimeout(() => {
          try {
            let f = fn(this.PromiseResult);
            if (f === promiseThen) {
              // 不能返回自身
              throw new Error("不能返回自身。。。");
            }
            if (f instanceof MyPromise) {
              // 如果是 Promise 则执行对应的回调
              f.then(resolve, reject);
            } else {
              // 如果不是 Promise 则直接成功
              resolve(f);
            }
          } catch (error) {
            // 处理报错, 预防一些边界情况
            reject(error);
            throw new Error(error);
          }
        });
      };
      // 如果成功,则执行成功回调
      // 如果失败,则执行失败回调
      if (this.PromiseState === "fulfilled") {
        // onFulfilled(this.PromiseResult);
        handlePromise(onFulfilled);
      } else if (this.PromiseState === "rejected") {
        // onRejected(this.PromiseResult);
        handlePromise(onRejected);
      } else if (this.PromiseState === "pending") {
        // 将成功回调放入队列
        this.onFulfilledCallbacks.push(handlePromise.bind(this, onFulfilled));
        // 将失败回调放入队列
        this.onRejectedCallbacks.push(handlePromise.bind(this, onRejected));
      }
    });

    // 返回包装的 Promise
    return promiseThen;
  }
}

测试:

const p = new MyPromise((resolve, reject) => {
  resolve(1);
}).then(
  (res) => console.log(res),
  (err) => console.log(err)
);

console.log(2);

在这里插入图片描述

2.3.其他方法

2.3.1.all

Promise.all()总结:

  1. 接收一个 Promise 数组,如果参数不是 Promise 则当做成功;
  2. 如果所有的 Promise 都成功,则返回成功的结果数组;
  3. 如果有一个 Promise 不成功,则返回这一次的失败结果;
static all(promises) {
   const result = []; // 都成功后会被返回的数组
   let count = 0; // 统计成功的次数
   return new MyPromise((resolve, reject) => {
     const addData = (index, value) => {
       result[index] = value; 
       count++;  // 成功一次则自增
       if (count === promises.length) {
   			resolve(result);
   		}
     };
     promises.forEach((promise, index) => {
       if (promise instanceof MyPromise) {
       	// 如果是 Promise,则链式调用将参数传递下去
         promise.then( (res) => {
             addData(index, res);
           },
           (err) => reject(err)
         );
       } else {
       	// 不是 Promise 也当做成功状态
         addData(index, promise);
       }
     });
   });
 }

测试:

const p1 = new MyPromise((resolve, reject) => {
  resolve(1);
});
const p2 = new MyPromise((resolve, reject) => {
  resolve(2);
});
const p3 = 3;

MyPromise.all([p1, p2, p3]).then((res) => {
  console.log(res);
});

在这里插入图片描述

2.3.2.race

Promise.race()总结:

  1. 接收一个 Promise 数组,如果参数不是 Promise 则当做成功;
  2. 哪个 Promise 最快得到结果,就返回那个结果,无论成功失败;
static race(promises) {
   return new MyPromise((resolve, reject) => {
     promises.forEach((promise, index) => {
       if (promise instanceof MyPromise) {
       	// 是Promise,则调用 then ,无论成功/失败都返回
         promise.then(
           (res) => resolve(res),
           (err) => reject(err)
         );
       } else {
       	// 不是Promise则直接返回
         resolve(promise);
       }
     });
   });
 }

测试:

const p1 = new MyPromise((resolve, reject) => {
  resolve(1);
});
const p2 = new MyPromise((resolve, reject) => {
  reject(2);
});
const p3 = 3;

MyPromise.race([p1, p2, p3]).then((res) => {
  console.log(res);
});

p3 先执行,因此返回 p3:

在这里插入图片描述

2.3.3.allsetled

Promise.allsetled()总结:

  1. 接收一个 Promise 数组,如果参数不是 Promise 则当做成功;
  2. 把每一个Promise的结果,集合成数组后返回;
static allSettled(promises) {
   return new MyPromise((resolve, reject) => {
     let result = [];
     let count = 0;
     let addData = (status, value, index) => {
       result[index] = {
         status,
         value,
       };
       count++;
       if (count === promises.length) {
         resolve(result);
       }
     };
     promises.forEach((promise, index) => {
       if (promise instanceof MyPromise) {
       	// 记录状态,不管成功失败都返回
         promise.then(
           (res) => addData("fulfilled", res, index),
           (err) => addData("rejected", err, index)
         );
       } else {
         addData("fulfilled", promise, index);
       }
     });
   });
 }

测试:

const p1 = new MyPromise((resolve, reject) => {
  resolve(1);
});
const p2 = new MyPromise((resolve, reject) => {
  reject(2);
});
const p3 = 3;

MyPromise.allSettled([p1, p2, p3]).then((res) => {
  console.log(res);
});

在这里插入图片描述

2.3.4.any

Promise.any()总结:

  1. 接收一个 Promise 数组,如果参数不是 Promise 则当做成功;
  2. 如果有一个Promise成功,则返回这个成功结果;
  3. 如果所有Promise都失败,则报错;
static any(promises) {
   return new MyPromise((resolve, reject) => {
     let count = 0;
     promises.forEach((promise, index) => {
       if (promise instanceof MyPromise) {
         promise.then(
           (res) => resolve(res),
           (err) => {
             count++;
             if (count === promises.length) {
               reject("都执行失败了~");
             }
           }
         );
       }
     });
   });
 }

测试:

const p1 = new MyPromise((resolve, reject) => {
  resolve(1);
});
const p2 = new MyPromise((resolve, reject) => {
  reject(2);
});
const p3 = 3;

MyPromise.any([p1, p2, p3]).then((res) => {
  console.log(res);
});

有一个成功则返回成功的那一个 Promise
在这里插入图片描述

测试:

const p1 = new MyPromise((resolve, reject) => {
  reject(1);
});
const p2 = new MyPromise((resolve, reject) => {
  reject(2);
});

MyPromise.any([p1, p2]).then((res) => {
  console.log(res);
});

错误数量和接收的数组长度一致,则抛出错误:
在这里插入图片描述

3.最终代码

class MyPromise {
  constructor(exector) {
    // 初始化状态及初始值
    this.initValue();
    // 初始化的时候改变 this 指向,将 this 指向实例对象
    this.initBind();
    // 执行器,当 new MyPromise()时,这个callback要接受 resolve 和 reject 函数
    try {
      // 正常执行的话,执行 exector
      exector(this.resolve, this.reject);
    } catch (error) {
      // 捕获到异常,则执行一次 reject
      this.reject(error);
    }
  }
  initValue() {
    this.PromiseState = "pending"; // Promise 状态
    this.PromiseResult = null; // Promise 返回值
    this.onFulfilledCallbacks = []; // 保存成功的回调
    this.onRejectedCallbacks = []; // 保存失败的回调
  }
  initBind() {
    this.resolve = this.resolve.bind(this);
    this.reject = this.reject.bind(this);
  }
  resolve(value) {
    // 只要状态已经改变,就不允许继续修改状态
    if (this.PromiseState !== "pending") {
      return;
    }
    // 此时状态改为 fulfilled
    this.PromiseState = "fulfilled";
    // 将传递进来的参数赋值
    this.PromiseResult = value;
    // 执行成功的回调
    while (this.onFulfilledCallbacks.length) {
      // 每次从队列中取出一个来执行
      this.onFulfilledCallbacks.shift()(this.PromiseResult);
    }
  }
  reject(reason) {
    // 只要状态已经改变,就不允许继续修改状态
    if (this.PromiseState !== "pending") {
      return;
    }
    // 此时状态改为 rejected
    this.PromiseState = "rejected";
    // 将传递进来的错误抛出
    this.PromiseResult = reason;
    // 执行成功的回调
    while (this.onRejectedCallbacks.length) {
      // 每次从队列中取出一个来执行
      this.onRejectedCallbacks.shift()(this.PromiseResult);
    }
  }
  then(onFulfilled, onRejected) {
    // then 函数接收两个callback,一个是成功回调,一个是失败回调
    // 参数兜底处理,确保返回的都是回调函数
    onFulfilled =
      typeof onFulfilled === "function" ? onFulfilled : (value) => value;
    onRejected =
      typeof onRejected === "function"
        ? onRejected
        : (reason) => {
            throw reason;
          };
    var promiseThen = new MyPromise((resolve, reject) => {
      const handlePromise = (fn) => {
        setTimeout(() => {
          try {
            let f = fn(this.PromiseResult);
            if (f === promiseThen) {
              // 不能返回自身
              throw new Error("不能返回自身。。。");
            }
            if (f instanceof MyPromise) {
              // 如果是 Promise 则执行对应的回调
              f.then(resolve, reject);
            } else {
              // 如果不是 Promise 则直接成功
              resolve(f);
            }
          } catch (error) {
            // 处理报错, 预防一些边界情况
            reject(error);
            throw new Error(error);
          }
        });
      };
      // 如果成功,则执行成功回调
      // 如果失败,则执行失败回调
      if (this.PromiseState === "fulfilled") {
        // onFulfilled(this.PromiseResult);
        handlePromise(onFulfilled);
      } else if (this.PromiseState === "rejected") {
        // onRejected(this.PromiseResult);
        handlePromise(onRejected);
      } else if (this.PromiseState === "pending") {
        // 将成功回调放入队列
        this.onFulfilledCallbacks.push(handlePromise.bind(this, onFulfilled));
        // 将失败回调放入队列
        this.onRejectedCallbacks.push(handlePromise.bind(this, onRejected));
      }
    });

    // 返回包装的 Promise
    return promiseThen;
  }
  static all(promises) {
    const result = [];
    let count = 0;
    return new MyPromise((resolve, reject) => {
      const addData = (index, value) => {
        result[index] = value;
        count++;
        if (count === promises.length) resolve(result);
      };
      promises.forEach((promise, index) => {
        if (promise instanceof MyPromise) {
          promise.then(
            (res) => {
              addData(index, res);
            },
            (err) => reject(err)
          );
        } else {
          addData(index, promise);
        }
      });
    });
  }

  static race(promises) {
    return new MyPromise((resolve, reject) => {
      promises.forEach((promise, index) => {
        if (promise instanceof MyPromise) {
          promise.then(
            (res) => resolve(res),
            (err) => reject(err)
          );
        } else {
          resolve(promise);
        }
      });
    });
  }

  static allSettled(promises) {
    return new MyPromise((resolve, reject) => {
      let result = [];
      let count = 0;
      let addData = (status, value, index) => {
        result[index] = {
          status,
          value,
        };
        count++;
        if (count === promises.length) {
          resolve(result);
        }
      };
      promises.forEach((promise, index) => {
        if (promise instanceof MyPromise) {
          promise.then(
            (res) => addData("fulfilled", res, index),
            (err) => addData("rejected", err, index)
          );
        } else {
          addData("fulfilled", promise, index);
        }
      });
    });
  }

  static any(promises) {
    return new MyPromise((resolve, reject) => {
      let count = 0;
      promises.forEach((promise, index) => {
        if (promise instanceof MyPromise) {
          promise.then(
            (res) => resolve(res),
            (err) => {
              count++;
              if (count === promises.length) {
                reject("都执行失败了~");
              }
            }
          );
        }
      });
    });
  }
}
  • 31
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

剑九 六千里

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值