Skip to content

Promise API

只处理成功超简版

typescript
class Promise {
  // 只处理成功
  constructor(executor) {
    this.cbs = [];

    const resolve = (value) => {
      queueMicrotask(() => {
        this.data = value;
        this.cbs.forEach((cb) => cb(value));
      });
    };

    executor(resolve);
  }

  then(onResolved) {
    return new Promise((resolve) => {
      this.cbs.push(() => {
        const res = onResolved(this.data);
        if (res instanceof Promise) {
          res.then(resolve);
        } else {
          resolve(res);
        }
      });
    });
  }
}

简单版本promise

  • 包含then的链式调用
typescript
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";

class MyPromise {
  constructor(executor) {
    this.value = undefined;
    this.reason = undefined;
    this.status = PENDING;
    // 存放成功的回调
    this.onFulfilledCallbacks = [];
    // 存放失败的回调
    this.onRejectedCallbacks = [];

    const resolve = value => {
      if (this.status === "pending") {
        this.status = "fulfilled";
        this.value = value;
        // 依次将对应的函数执行
        this.onFulfilledCallbacks.forEach(fn => fn());
      }
    };

    const reject = reason => {
      if (this.status === "pending") {
        this.status = "rejected";
        this.reason = reason;
        this.onRejectedCallbacks.forEach(fn => fn());
      }
    };

    try {
      // executor内部执行一个异步任务
      // 1. 当异步任务成功时调用resolve(value)
      // 2. 失败时调用reject(reason)
      executor(resolve, reject);
    } catch (error) {
      reject(error);
    }
  }

  // 工具函数, 判断function
  isFunction(value) {
    return typeof value === "function";
  }

  // 调用 then 方法来注册当promise状态改变时的回调
  //   这些函数会被存储起来,等待promise状态改变时,才执行
  //   .then里面接收两个参数,一个是成功的回调,一个是失败的回调
  // onFulfilled,onRejected => 是一个函数

  then(onFulfilled, onRejected) {
    // then().then() then可以传空值
    onFulfilled = this.isFunction(onFulfilled) ? onFulfilled : val => val;
    // prettier-ignore
    onRejected = this.isFunction(onRejected)? onRejected : reason => {throw reason}
    // 为了链式调用这里直接创建一个 MyPromise,并在后面 return 出去
    const promise2 = new MyPromise((resolve, reject) => {
      // fulfilled处理
      const fulfilledMicrotask = () => {
        // 创建一个微任务等待 promise2 完成初始化
        queueMicrotask(() => {
          try {
            // 获取成功回调函数的执行结果
            const x = onFulfilled(this.value);
            // 传入 resolvePromise 集中处理
            // this.resolvePromise(promise2, x, resolve, reject);
            // x instanceof MyPromise ? x.then(resolve, reject) : resolve(x)
            resolve(x);
          } catch (e) {
            reject(e);
          }
        });
      };
      // rejected处理
      const rejectedMicrotask = () => {
        queueMicrotask(() => {
          try {
            // 调用失败回调,并且把原因返回
            const x = onRejected(this.reason);
            // this.resolvePromise(promise2, x, resolve, reject);
            // x instanceof MyPromise ? x.then(resolve, reject) : resolve(x)
            resolve(x);
          } catch (e) {
            reject(e);
          }
        });
      };
      // 判断状态
      switch (this.status) {
        case FULFILLED: {
          fulfilledMicrotask();
          break;
        }
        case REJECTED: {
          rejectedMicrotask();
          break;
        }
        case PENDING: {
          this.onFulfilledCallbacks.push(fulfilledMicrotask);
          this.onRejectedCallbacks.push(rejectedMicrotask);
        }
      }
    });
    // then 返回promise2 实现链式调用
    return promise2;
  } // end then
}

// 测试test
const promise = new MyPromise((resolve, reject) => {
  setTimeout(() => {
    resolve("成功");
  }, 1000);
}).then(
  data => {
    console.log("success", data);
    return 666;
  },
  err => {
    console.log("faild", err);
  }
);
promise.then(value => console.log("Handler 1: ", value));

promise.then(value => console.log("Handler 2: ", value));

实例方法

  • Promise.prototype.then()
  • Promise.prototype.catch()
  • Promise.prototype.finally()

静态方法

  • Promise.all()
  • Promise.race()
  • Promise.allSettled()
  • Promise.any()
  • Promise.resolve()
  • Promise.reject()

Promise.all

Promise.all 方法接受一个 promise 数组作为输入,并返回一个新的 promise,该 promise 等待所有的输入 promise 都完成。如果所有的 promise 都成功解决,新的 promise 将以一个包含所有解决值的数组形式解决。如果输入数组中的任何一个 promise 被拒绝,新的 promise 会立即以这个拒绝的原因被拒绝。

  1. 参数可迭代
  2. 返回值是promise
  3. 如果全部成功,状态变为resolve
  4. 但凡有一个失败,状态变为reject
typescript
// 判断参数是否是可迭代对象
function isIterable(obj) {
  // 检查对象是否为 null 或 undefined
  return obj != null && typeof obj[Symbol.iterator] === 'function';
}
typescript
function promiseAll(promises) {
  // 1. 首先判断参数是否是可迭代对象
  if (!isIterable(promises)) {
    return new TypeError(`${promises} is not iterable`)
  }
  return new Promise((resolve, reject) => {
    let result = [] // 存放结果
    let count = 0 // 进入fullfilled的promise个数

    promises.forEach((p, i) => {
      // 包装非promise值,保证可迭代元素为promise
      Promise.resolve(p)
        .then((res) => {
          result[i] = res
          // 当所有的都resolve了,resolve
          if (++count === promises.length) resolve(result)
        })
        // 只要有一个reject,就reject出去
        .catch((err) => reject(err))
    })
  })
}

Promise.race

Promise.race() 方法接收一个 promise 数组作为参数,并返回一个新的 promise 对象。这个新返回的 promise 等待参数数组中的第一个完成的 promise,并采用它的状态(fulfilled 或 rejected)

typescript
function promiseRace(promises) {
  return new Promise((resolve, reject) => {
    promises.forEach(promise => {
      // 当任何一个promise解决或拒绝时,由于resolve()和reject()会改变promise的状态,
      // 所以只有第一个状况会被处理
      Promise.resolve(promise)
        .then(value => resolve(value))
        .catch(error => reject(error));
    });
  });
}

Promise.allSettled

Promise.allSettled()方法接受一个数组作为参数,数组的每个成员都是一个 Promise 对象,并返回一个新的 Promise 对象。只有等到参数数组的所有 Promise 对象都发生状态变更(不管是fulfilled还是rejected),返回的 Promise 对象才会发生状态变更。

typescript
function promiseAllSettled(promises) {
  let wrappedPromises = promises.map(promise =>
    Promise.resolve(promise)
      .then(
        value => ({ status: 'fulfilled', value }),
        reason => ({ status: 'rejected', reason }),
      )
  );
  return Promise.all(wrappedPromises);
}


// 示例
let promise1 = Promise.resolve('Promise 1');
let promise2 = Promise.reject('Promise 2');
promiseAllSettled([promise1, promise2])
  .then(results => console.log(results));

对每个 Promise 对象使用 Promise.resolve() 方法和添加 .then() ,将每个 Promise 包装成一个永远不会被拒绝的新 Promise,这个新的 Promise 总是解决并给出描述原始 Promise 结果的对象

Promise.any

只要参数实例有一个变成fulfilled状态,包装实例就会变成fulfilled状态;如果所有参数实例都变成rejected状态,包装实例就会变成rejected状态。 Promise.any()跟Promise.race()方法很像,只有一点不同,就是Promise.any()不会因为某个 Promise 变成rejected状态而结束,必须等到所有参数 Promise 变成rejected状态才会结束。

typescript
function promiseAny(promises) {
  return new Promise((resolve, reject) => {
    // 存错误状态
    let errors = [];
    promises.forEach(promise => {
      Promise.resolve(promise)
        .then(value => resolve(value))
        .catch(error => {
          errors.push(error);
          // 当所有的都Error了,才reject
          if(errors.length === promises.length) {
            reject(new AggregateError(errors, "All promises were rejected"));
          }
        })
    });
  });
}

Promise.resolve

typescript
// resolve 静态方法
static resolve (value) {
    // 如果传入 MyPromise 就直接返回
    if (value instanceof MyPromise) return value
    // 普通值,创建promise对象
    return new MyPromise(resolve => resolve(value))
}
typescript
// Promise.resolve() 方法的实现
function promiseResolve(value) {
  // 是Promise实例,直接返回即可
  if (value instanceof Promise) return value
  return new Promise((resolve) => {
    resolve(value);
  });
}

Promise.reject

typescript
// reject 静态方法
static reject (reason) {
    return new MyPromise((resolve, reject) => {
        reject(reason)
    })
}
typescript
function promiseReject(reason) {
  return new Promise((_, reject) => {
    reject(reason);
  });
}

_.prototype.catch()

实例方法

typescript
  // catch方法实际上是一个没有onResolved,只有onRejected参数的特别的then方法:
this.catch = function (errCallback) {
  return this.then(null, errCallback);
};

// 原型上挂载
Promise.prototype.catch = function(errCallback){
  return this.then(undefined,errCallback)
}

// 构造函数中写法
catch (failCallback) {
    return this.then(undefined, failCallback)
}

eg.

typescript
const p = () => {
    return new Promise((resolve,reject)=>{
        reject('失败了哦')
    })
}

p().then(value => console.log(value))
    .catch(reason => console.log(reason))
// failCallback ::: reason => console.log(reason)

_.prototype.finally()

  1. 无论当前promise状态是成功或者失败,finally中的回调始终会执行一次
  2. 在finally()方法的后面可以链式调用then方法,拿到当前promise对象最终返回的结果
typescript
// finally方法用于注册一个在Promise结束时,无论结果是fulfilled还是rejected都会执行的回调函数。
this.finally = function (callback) {
  return this.then(
    value => MyPromise.resolve(callback()).then(() => value),
    reason => MyPromise.resolve(callback()).then(() => { throw reason })
  );
};


// class Mypromise中写法
finally (callback) {
  return this.then(
    // Promise包装是保证异步等待执行后面的then方法
    value => MyPromise.resolve(callback()).then(() => value),
    // throw reason
    reason => return MyPromise.resolve(callback()).then(() => {throw reason})
    )
}