手写Promise

334 阅读2分钟

前言

如果想实现一个Promise 需要从以下几个方面考虑

  • 符合 promise A+规范
  • Promise类的设计
  • 状态设计(pending/fulfilled/reject)
  • 如何实现 resolve
  • 如何实现 reject
  • 如何实现 then

什么是Promise A+ 规范

promisesaplus

  1. “promise” is an object or function with a then method whose behavior conforms to this specification.
  2. “thenable” is an object or function that defines a then method.
  3. “value” is any legal JavaScript value (including undefined, a thenable, or a promise).
  4. “exception” is a value that is thrown using the throw statement.
  5. “reason” is a value that indicates why a promise was rejected.
  6. A promise must be in one of three states: pending, fulfilled, or rejected.

promise类的设计

我们在使用 Promise的时候,都是通过 new 关键字调用, 所以借助 ES6 class 实现 Promise的声明

class DDFPromise {
  constructor(executor) {
    executor(executor);
  }

实现Promise 三种状态

我们在使用Promise时,注意到,Promise有三种状态 fulfill/reject/pending

  • new Promise(()=> {}) 此时的状态为pending
  • new Promise(()=> {}).then() 此时的状态为fulfill
  • new Promise(()=> {}).catch() 此时的状态为reject
const PENDING_STATUS = "pending";
const FULFILL_STATUS = "fulfill";
const REJECT_STATUS = "reject";
class DDFPromise {
    constructor(executor) {
        this.status = PENDING_STATUS;
        executor(executor);
     }
}

new DDFPromise(() => {
  console.log("代码执行");
});

如何实现 resolve

实现resolve 需要关注两个点

  • 状态
  • 返回值
const PENDING_STATUS = "pending";
const FULFILL_STATUS = "fulfill";
const REJECT_STATUS = "reject";
class DDFPromise {
    constructor(executor) {
      this.status = PENDING_STATUS;
      this.value = null;
      const resolve = (value) => {
        if (this.status === PENDING_STATUS) {
          this.status = FULFILL_STATUS;
          console.log("resolve被执行", value);
**          **this.value = value
       }
     };
      executor(resolve);
     }
}

new DDFPromise((resolve) => resolve("resolve传入的参数"))

如何实现 reject

实现resolve 需要关注两个点

  • 状态
  • 返回值
const PENDING_STATUS = "pending";
const FULFILL_STATUS = "fulfill";
const REJECT_STATUS = "reject";
class DDFPromise {
    constructor(executor) {
      this.status = PENDING_STATUS;
      this.value = null;
      const resolve = (value) => {
        if (this.status === PENDING_STATUS) {
          this.status = FULFILL_STATUS;
          console.log("resolve被执行", value);
          this.value = value
       }
     };
      const reject = (reason) => {
        if (this.status === PENDING_STATUS) {
          this.status = REJECT_STATUS;
          this.reason = reason;
       }
     };
      executor(resolve, reject);
     }
}

new DDFPromise((resolve, reject) => {
  resolve("resolve传入的参数");
  reject("reject传入的参数");
})

如何实现 then

实现then 需要关注 以下几点

  • then方法的两个入参
  • then方法的两个入参 如何与constructor中定义的resolve/reject做关联

const PENDING_STATUS = "pending";
const FULFILL_STATUS = "fulfill";
const REJECT_STATUS = "reject";
class DDFPromise {
  constructor(executor) {
    this.status = PENDING_STATUS;
    this.value = null;
    this.reason = null;
    const resolve = (value) => {
      if (this.status === PENDING_STATUS) {
        this.status = FULFILL_STATUS;
        this.value = value;
        this.onfulfilled(this.value);
      }
    };
    const reject = (reason) => {
      if (this.status === PENDING_STATUS) {
        this.status = REJECT_STATUS;
        this.reason = reason;
        this.onrejected(this.reason);
      }
    };
    executor(resolve, reject);
  }
  
  then(onfulfilled, onrejected) {
    this.onfulfilled = onfulfilled;
    this.onrejected = onrejected;
  }
}

const ddfPro = new DDFPromise((resolve, reject) => {
    resolve("resolve传入的参数");
    // reject("reject传入的参数");
});

ddfPro.then(
    (res) => {
      console.log("fulfilled", res);
    },
    (err) => {
      console.log("reject", err);
    }
);

上边代码执行时报错 this.onfulfilled is not a function,报错的原因:new Prose(()=>{}) 入参的代码会立刻执行,而执行时this.onrejected,还没有声明,其实我们可以借助 Event Loop 解决此问题

解决then方法声明 调用时报错

queueMicrotask | setTimeout

const PENDING_STATUS = "pending";
const FULFILL_STATUS = "fulfill";
const REJECT_STATUS = "reject";
class DDFPromise {
  constructor(executor) {
    this.status = PENDING_STATUS;
    this.value = null;
    this.reason = null;
    const resolve = (value) => {
      if (this.status === PENDING_STATUS) {
        this.status = FULFILL_STATUS;
        queueMicrotask(() => {
          this.value = value;
          this.onfulfilled(this.value);
        });
     }
  };
  const reject = (reason) => {
    if (this.status === PENDING_STATUS) {
       this.status = REJECT_STATUS;
       queueMicrotask(() => {
         this.reason = reason;
         this.onrejected(this.reason);
       });
      }
    };
    executor(resolve, reject);
  }
  then(onfulfilled, onrejected) {
    this.onfulfilled = onfulfilled;
    this.onrejected = onrejected;
  }
}

const ddfPro = new DDFPromise((resolve, reject) => {
// resolve("resolve传入的参数");

// reject("reject传入的参数");
});

ddfPro.then(
  (res) => {
     console.log("fulfilled", res);
  },
  (err) => {
    console.log("reject", err);
  }
);

总结

经过如上步骤,只完成了Promise的基本操作,