JavaScript异步编程规范->实现一个简易版本的 Promise

文章目录

  • 1.Promise基本使用
  • 2.实现一个Promise
    • 2.1.resolve/reject
      • 2.1.1.初始化状态及返回值
      • 2.1.2.实现resolve/reject
      • 2.1.3.状态不可逆
      • 2.1.4.处理throw
    • 2.2.then
      • 2.2.1.实现then
      • 2.2.2.通过队列实现setTimeout
      • 2.2.3.链式调用
      • 2.2.4.执行顺序
    • 2.3.其他方法
      • 2.3.1.all
      • 2.3.2.race
      • 2.3.3.allsetled
      • 2.3.4.any
  • 3.最终代码


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 = null; // 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 = null; // 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 = null; // 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 {
      // 捕获到异常,则执行一次 reject
      this.reject();
    }
  }
  initValue() {
    this.PromiseState = "pending"; // Promise 状态
    this.PromiseResult = null; // 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 {
      // 补货到异常,则执行一次 reject
      this.reject();
    }
  }
  initValue() {
    this.PromiseState = "pending"; // Promise 状态
    this.PromiseResult = null; // 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 {
      // 补货到异常,则执行一次 reject
      this.reject();
    }
  }
  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;
          };

    // 如果成功,则执行成功回调
    // 如果失败,则执行失败回调
    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 (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) => {
        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 (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;
  }
}

测试:

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("都执行失败了~");
              }
            }
          );
        }
      });
    });
  }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/506272.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

量化交易入门(三十四)DMI指标学习和应用

什么是DMI指标 DMI(Dynamic Momentum Index)指标是一种趋势型指标,由威尔斯威尔德(Welles Wilder)于1978年提出。它通过比较价格的正向和负向变动幅度来衡量市场趋势的强度和方向。 DMI指标由三部分组成: DI(Positive Directional Indicator):衡量价格上涨趋势的强度。-DI(N…

域攻防渗透之委派攻击

出身寒微,不是耻辱,能屈能伸,方为丈夫。 约束性委派的利用 原理 非约束性委派被委派的机器会直接得到发布委派的用户的TGT,是十分不安全的,因此微软推出了约束性委派,还扩充kerberos协议,添加…

适用于 Linux 的 Windows 子系统安装初体验

1、简述 Windows Subsystem for Linux (WSL) 是 Windows 的一项功能,允许您在 Windows 计算机上运行 Linux 环境,而无需单独的虚拟机或双重启动。 WSL 旨在为想要同时使用 Windows 和 Linux 的开发人员提供无缝且高效的体验。 使用 WSL 安装和运行各种 L…

PWM波输出-定时器输出比较单元

目录 1,前言 2,实现过程 2.1 比较部分 2.2 输出部分 1,前言 电平,作为单片机的“肌肉”,承担着实践单片机的“想法“的重要任务。而PWM波,则是电平这个大类的重中之重,可以说,没…

代码随想录Day24:回溯算法Part1

回溯算法理论: Leetcode 77. 组合 这道题其实有点绕的我头晕,对于start index的解释我能够理解,但是我很难去想清楚他是如何在一次次递归中变化的因为他在for循环外面扮演我们每一次在一个数字找完了他开头的所有组合之后,就把st…

题目:图书排序(蓝桥OJ 4397)

问题描述&#xff1a; 解题思路&#xff1a; 可以使用结构体数组并排序&#xff0c;需要注意的是结构体数组不能直接使用sort进行排序,要自己写cmp函数。 结构体的cmp具体写法&#xff1a; bool cmp(book a, book b) { // 结构体类型名做参数if (a.w b.w) return a.id <…

短剧猫H5页面html源码

短剧猫H5页面html源码&#xff0c;包含一个接口&#xff0c;像俩天块样式发送剧名回复网盘链接&#xff0c;文件上传解压就能用。 源码免费下载地址抄笔记 (chaobiji.cn)https://chaobiji.cn/

53 v-bind 和 v-model 的实现和区别

前言 这个主要的来源是 偶尔的情况下 出现的问题 就比如是 el-select 中选择组件之后, 视图不回显, 然后 model 不更新等等 这个 其实就是 vue 中 视图 -> 模型 的数据同步, 我们通常意义上的处理一般是通过 模型 -> 数据 的数据同步, 比如 我们代码里面更新了 model.…

进程、线程、协程

进程、线程、协程 进程、线程、协程进程概念生命周期进程的五状态模型进程同步机制进程通信机制死锁进程调度算法 线程概念生命周期线程同步机制互斥锁信号量条件变量读写锁 线程通信机制线程死锁 协程进程、线程、协程对比进程与线程比较协程与线程比较 如何选择进程、线程、协…

【Vue3】el-checkbox-group实现权限配置和应用

一. 需求 针对不同等级的用户&#xff0c;配置不同的可见项 配置效果如下 &#xff08;1&#xff09;新增&#xff0c;获取数据列表 &#xff08;2&#xff09;编辑&#xff0c;回显数据列表 应用效果如下 &#xff08;1&#xff09;父级配置 &#xff08;2&#xff09;子级…

【Selenium+python】自动化测试登录界面

前言&#xff1a;已经学习selenium许久了&#xff0c;奈何公司的项目还在码代码中...&#xff0c;感觉自己学的东西快忘的差不多了&#xff0c;所以就找个网站练练手&#xff0c;顺便回顾一下UI自动化的知识&#xff0c;也希望跟我一样的小白有所受益。 一、用例分析&#xff…

Benjamin Button‘sLetter to Daughter 英语阅读

Benjamin ButtonsLetter to Daughter 来源: The Curious Case of Benjamin Button 官方翻译 For what its worth: Its never too late, or in my case, too early to bewhoever you want to be. Theres no time limit. Start whenever you want. You can change or stay t…

向量点乘有哪些作用呢

如下&#xff1a; 1.找到两个向量之间的夹角(不用多说) 2.求一个向量投影在另一个向量的投影&#xff1a; 我们把图中b的在a上的投影向量称作b1吧&#xff0c;因为b1就在a上&#xff0c;所以只需要求出b1的大小&#xff0c;然后乘以a的单位向量&#xff0c;我们就得到向量b1了…

【LeetCode热题100】114. 二叉树展开为链表(二叉树)

一.题目要求 给你二叉树的根结点 root &#xff0c;请你将它展开为一个单链表&#xff1a; 展开后的单链表应该同样使用 TreeNode &#xff0c;其中 right 子指针指向链表中下一个结点&#xff0c;而左子指针始终为 null 。展开后的单链表应该与二叉树 先序遍历 顺序相同。 …

KeepAlived使用介绍

目录 1、Introduce 2、基本使用 &#xff08;1&#xff09;安装 &#xff08;2&#xff09;配置文件 &#xff08;3&#xff09;使用教程 1、Introduce keepalived是一个用于实现高可用性和负载均衡的开源软件。它提供了一种轻量级的方式来管理多个服务器&#xff0c;并确保…

隐私计算实训营学习六:隐语PIR介绍及开发指南

文章目录 一、隐语实现的PIR总体介绍1.1 PIR的定义和种类1.2 隐语PIR功能分层 二、Index PIR-SealPIR介绍三、Keyword PIR- Labeled PSI介绍四、隐语PIR后续计划 一、隐语实现的PIR总体介绍 1.1 PIR的定义和种类 PIR(Private Information Retrieval PIR)隐匿查询&#xff1a;…

YOLOv8改进 | 低照度检测 | 2024最新改进CPA-Enhancer链式思考网络(适用低照度、图像去雾、雨天、雪天)

一、本文介绍 本文给大家带来的2024.3月份最新改进机制&#xff0c;由CPA-Enhancer: Chain-of-Thought Prompted Adaptive Enhancer for Object Detection under Unknown Degradations论文提出的CPA-Enhancer链式思考网络&#xff0c;CPA-Enhancer通过引入链式思考提示机制&am…

使用虚幻引擎为AR体验提供动力

Powering AR Experiences with Unreal Engine ​​​​​​​ 目录 1. 虚幻引擎概述 2. 虚幻引擎如何为AR体验提供动力 3. 虚幻引擎中AR体验的组成部分是什么&#xff1f; 4. 使用虚幻引擎创建AR体验 5. 虚幻引擎中AR的优化提示 6. 将互动性融入AR与虚幻引擎 7. 在AR中…

C++_Function包装器和bind

文章目录 前言第一种第二种 仿函数第三种 lambda表达式 一、Function包装器二、使用场景三、std::bind 前言 到目前为止的学习&#xff0c;我们知晓了三种方式来传函数。 第一种 #include<iostream>int Plus(int i, int j) {return i j; }int main() {int(*func)(int…

从大厂裸辞半年,我靠它成功赚到了第一桶金,如果你失业了,建议这样做,不然时间太久了就完了

程序员接私活和创业是许多技术从业者关注的话题。下面我将介绍一些程序员接私活和创业的渠道和建议&#xff1a; 接私活的渠道&#xff1a; 自媒体平台&#xff1a; 可以利用社交媒体、个人博客、技术社区等平台展示自己的作品和技能&#xff0c;吸引潜在客户。自由工作平台&…