面试:手写promise

1,119 阅读2分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

前言

promise 作为 ES6 的重要产物,在日常的开发工作中有着重要的地位。所以 promise 作为一个高频的面试题,用来考察候选人的基础知识功底。

promise

Promise 对象用于表示一个异步操作的最终完成 (或失败)及其结果值。

一个 Promise 对象代表一个在这个 promise 被创建出来时不一定已知的值。它让您能够把异步操作最终的成功返回值或者失败原因和相应的处理程序关联起来。 这样使得异步方法可以像同步方法那样返回值:异步方法并不会立即返回最终的值,而是会返回一个 promise,以便在未来某个时候把值交给使用者。

一个 Promise 必然处于以下几种状态之一:

  • 待定(pending) : 初始状态,既没有被兑现,也没有被拒绝。
  • 已兑现(fulfilled) : 意味着操作成功完成。
  • 已拒绝(rejected) : 意味着操作失败。

待定状态的 Promise 对象要么会通过一个值 被兑现(fulfilled) ,要么会通过一个原因(错误)被拒绝(rejected),当这些情况之一发生时,我们用 promise 的 then 方法排列起来的相关处理程序就会被调用。

因为 Promise.prototype.then 和  Promise.prototype.catch 方法返回的是 promise, 所以它们可以被链式调用。

手写promise

function MyPromise(executor) {
    let self = this;
    // 初始化状态
    this.status = 'padding';
    // 成功的值
    this.value = undefined;
    // 失败原因
    this.reason = undefined;
    // resolve 的回调
    this.resolveCallback = [];
    // reject 的回调
    this.rejectCallback = [];
    
    // resolve逻辑
    function resolve(value) {
      if (self.status === 'padding') {
        console.log('resolve: ', this);
        self.value = value;
        self.status = 'fulfilled';
        self.resolveCallback.forEach((fn) => {
          fn();
        });
      }
    }
    
    // reject 逻辑
    function reject(reason) {
      if (self.status === 'padding') {
        console.log('reject: ', this);
        self.reason = reason;
        self.status = 'rejected';
        self.rejectCallback.forEach((fn) => {
          fn();
        });
      }
    }
    
    // 执行结果
    executor(resolve, reject);
  }
  
  // then 方法拿到 promise 的执行结果
  MyPromise.prototype.then = function (onFulfilled, onRejected) {
    let self = this;
    if (self.status === 'padding') {
      console.log('padding');
      self.resolveCallback.push(() => onFulfilled(self.value));
      self.rejectCallback.push(() => onRejected(self.reason));
    }
    if (self.status === 'fulfilled') {
      onFulfilled(self.value);
    }
    if (self.status === 'rejected') {
      onRejected(self.reason);
    }
  };

结语

如果这篇文章帮到了你,欢迎点赞👍和关注⭐️。

文章如有错误之处,希望在评论区指正🙏🙏。