Skip to content

Promise关键代码实现

基础逻辑实现

TIP

Promise一共有三种状态statusPending,Fulfilled以及Rejected

Promise初始状态为PENDING,如果Promise处于Pendingresolve后,进入Fulfilled状态,reject则进入Rejected状态。

定义完Promise类后,then方法包含onFulFilledonRejected两个回调函数,根据status判断。

1. 基础结构

js
// 基础结构 
// const promise = new MyPromise((resolve, reject) => {
// 	resolve('success');
// 	reject('fail');
// });
// MyPromise.js
class MyPromise {
    constructor(executor) {
        executor(resolve, reject);
    }
    resolve = () => {};
    reject = () => {};
}

if (typeof module !== "undefined" && module.exports) {
  // 在 Node.js 环境中
  module.exports = MyPromise;
}
// 基础结构 
// const promise = new MyPromise((resolve, reject) => {
// 	resolve('success');
// 	reject('fail');
// });
// MyPromise.js
class MyPromise {
    constructor(executor) {
        executor(resolve, reject);
    }
    resolve = () => {};
    reject = () => {};
}

if (typeof module !== "undefined" && module.exports) {
  // 在 Node.js 环境中
  module.exports = MyPromise;
}

2. 状态转换

js
// 定义三种状态 
const PENDING = 'pending'; 
const FULFILLED = 'fulfilled'; 
const REJECTED = 'rejected'; 

class MyPromise {
    constructor(executor) {
        executor(this.resolve, this.reject);
    }
    
    // 存储成功的参数 
    res = null;	
    // 存储失败的参数 
    err = null; 
    // 初始状态 
    status = PENDING; 
    
    resolve = (res) => { 
        // 如果成功且状态为PENDING 
        if(this.status === PENDING) { 
            this.status = FULFILLED; 
            this.res = res; 
        } 
    }; 
    reject = (err) => { 
        if(this.status === PENDING) { 
        	this.status = REJECTED; 
            this.err = err; 
        } 
    }; 
}
// 定义三种状态 
const PENDING = 'pending'; 
const FULFILLED = 'fulfilled'; 
const REJECTED = 'rejected'; 

class MyPromise {
    constructor(executor) {
        executor(this.resolve, this.reject);
    }
    
    // 存储成功的参数 
    res = null;	
    // 存储失败的参数 
    err = null; 
    // 初始状态 
    status = PENDING; 
    
    resolve = (res) => { 
        // 如果成功且状态为PENDING 
        if(this.status === PENDING) { 
            this.status = FULFILLED; 
            this.res = res; 
        } 
    }; 
    reject = (err) => { 
        if(this.status === PENDING) { 
        	this.status = REJECTED; 
            this.err = err; 
        } 
    }; 
}

3. then()方法实现

js
// 定义三种状态
const PENDING = 'pending'; 
const FULFILLED = 'fulfilled'; 
const REJECTED = 'rejected'; 

class MyPromise {
    constructor(executor) {
        executor(this.resolve, this.reject);
    }
    
    // ...
    
    then(onFulfilled, onRejected) {  
        if(this.status === FULFILLED) {  
            onFulfilled(this.res);  
        } else if(this.status === REJECTED) {  
            onRejected(this.err);  
        }  
    }  
}
// 定义三种状态
const PENDING = 'pending'; 
const FULFILLED = 'fulfilled'; 
const REJECTED = 'rejected'; 

class MyPromise {
    constructor(executor) {
        executor(this.resolve, this.reject);
    }
    
    // ...
    
    then(onFulfilled, onRejected) {  
        if(this.status === FULFILLED) {  
            onFulfilled(this.res);  
        } else if(this.status === REJECTED) {  
            onRejected(this.err);  
        }  
    }  
}
核心逻辑代码与测试
js
// 定义三种状态
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";

class MyPromise {
  constructor(executor) {
    executor(this.resolve, this.reject);
  }

  // 存储成功的参数
  res = null;
  // 存储失败的参数
  err = null;
  // 初始状态
  status = PENDING;

  resolve = (res) => {
    // 如果成功且状态为PENDING
    if (this.status === PENDING) {
      this.status = FULFILLED;
      this.res = res;
    }
  };
  reject = (err) => {
    if (this.status === PENDING) {
      this.status = REJECTED;
      this.err = err;
    }
  };

  then(onFulfilled, onRejected) {
    if (this.status === FULFILLED) {
      onFulfilled(this.res);
    } else if (this.status === REJECTED) {
      onRejected(this.err);
    }
  }
}

if (typeof module !== "undefined" && module.exports) {
  // 在 Node.js 环境中
  module.exports = MyPromise;
}
// 定义三种状态
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";

class MyPromise {
  constructor(executor) {
    executor(this.resolve, this.reject);
  }

  // 存储成功的参数
  res = null;
  // 存储失败的参数
  err = null;
  // 初始状态
  status = PENDING;

  resolve = (res) => {
    // 如果成功且状态为PENDING
    if (this.status === PENDING) {
      this.status = FULFILLED;
      this.res = res;
    }
  };
  reject = (err) => {
    if (this.status === PENDING) {
      this.status = REJECTED;
      this.err = err;
    }
  };

  then(onFulfilled, onRejected) {
    if (this.status === FULFILLED) {
      onFulfilled(this.res);
    } else if (this.status === REJECTED) {
      onRejected(this.err);
    }
  }
}

if (typeof module !== "undefined" && module.exports) {
  // 在 Node.js 环境中
  module.exports = MyPromise;
}
js
const MyPromise = require("./myPromise");

const promise = new MyPromise((resolve, reject) => {
    // resolve("成功"); // 输出 onFulfilled 成功
  reject("失败"); // 输出 onRejected 失败
});

promise.then(
  (res) => {
    console.log(`onFulfilled ${res}`);
  },
  (err) => {
    console.log(`onRejected ${err}`);
  }
);
const MyPromise = require("./myPromise");

const promise = new MyPromise((resolve, reject) => {
    // resolve("成功"); // 输出 onFulfilled 成功
  reject("失败"); // 输出 onRejected 失败
});

promise.then(
  (res) => {
    console.log(`onFulfilled ${res}`);
  },
  (err) => {
    console.log(`onRejected ${err}`);
  }
);

加入异步逻辑

现在调用的方式改为setTimeout异步的方式

js
const MyPromise = require("./myPromise");

const promise = new MyPromise((resolve, reject) => {
  setTimeout(() => {
    // resolve("成功");
    reject("失败");
  });
});

promise.then(
  (res) => {
    console.log(`onFulfilled ${res}`);
  },
  (err) => {
    console.log(`onRejected ${err}`);
  }
);
const MyPromise = require("./myPromise");

const promise = new MyPromise((resolve, reject) => {
  setTimeout(() => {
    // resolve("成功");
    reject("失败");
  });
});

promise.then(
  (res) => {
    console.log(`onFulfilled ${res}`);
  },
  (err) => {
    console.log(`onRejected ${err}`);
  }
);

此时发现,输出为空。

  • 原因在于:then是同步方法,调用then的时候,setTimeout作为宏任务还没有执行,那么promise.status === Pending,既不会走onFulfilled也不会走onRejected

  • 解决方法:因此,我们只需要在then添加新的逻辑,当状态仍为Pending的时候单独处理,存储onFulfilledonRejected作为回调的函数callback,当转换状态的时候,执行对应的回调函数onFulfilledCallback/onRejectedCallback

js
// MyPromise.js 

// ...
class MyPromise {
  constructor(executor) {
    executor(this.resolve, this.reject);
  }

  // 存储成功的参数
  res = null;
  // 存储失败的参数
  err = null;
  // 初始状态
  status = PENDING;
    
  // 存储成功/失败的回调函数
  onFulfilledCallback = null; 
  onRejectedCallback = null; 

  resolve = (res) => {
    // 如果成功且状态为PENDING
    if (this.status === PENDING) {
      this.status = FULFILLED;
      this.res = res;
      // 如果有成功的回调函数就执行  
      this.onFulfilledCallback && this.onFulfilledCallback(res); 
    }
  };
  reject = (err) => {
    if (this.status === PENDING) {
      this.status = REJECTED;
      this.err = err;
      // 如果有失败的回调函数就执行  
      this.onRejectedCallback && this.onRejectedCallback(err); 
    }
  };

  then(onFulfilled, onRejected) {
    if (this.status === FULFILLED) {
      onFulfilled(this.res);
    } else if (this.status === REJECTED) {
      onRejected(this.err);
    } else if (this.status === PENDING) { 
      this.onFulfilledCallback = onFulfilled; 
      this.onRejectedCallback = onRejected; 
    } 
  }
}

if (typeof module !== "undefined" && module.exports) {
  // 在 Node.js 环境中
  module.exports = MyPromise;
}
// MyPromise.js 

// ...
class MyPromise {
  constructor(executor) {
    executor(this.resolve, this.reject);
  }

  // 存储成功的参数
  res = null;
  // 存储失败的参数
  err = null;
  // 初始状态
  status = PENDING;
    
  // 存储成功/失败的回调函数
  onFulfilledCallback = null; 
  onRejectedCallback = null; 

  resolve = (res) => {
    // 如果成功且状态为PENDING
    if (this.status === PENDING) {
      this.status = FULFILLED;
      this.res = res;
      // 如果有成功的回调函数就执行  
      this.onFulfilledCallback && this.onFulfilledCallback(res); 
    }
  };
  reject = (err) => {
    if (this.status === PENDING) {
      this.status = REJECTED;
      this.err = err;
      // 如果有失败的回调函数就执行  
      this.onRejectedCallback && this.onRejectedCallback(err); 
    }
  };

  then(onFulfilled, onRejected) {
    if (this.status === FULFILLED) {
      onFulfilled(this.res);
    } else if (this.status === REJECTED) {
      onRejected(this.err);
    } else if (this.status === PENDING) { 
      this.onFulfilledCallback = onFulfilled; 
      this.onRejectedCallback = onRejected; 
    } 
  }
}

if (typeof module !== "undefined" && module.exports) {
  // 在 Node.js 环境中
  module.exports = MyPromise;
}

多次调用then

两个🌰
js
const MyPromise = require("./myPromise");

const promise = new MyPromise((resolve, reject) => {
  resolve("成功");
});

promise.then(
  (res) => {
    console.log(`onFulfilled ${res}`);
  },
  (err) => {
    console.log(`onRejected ${err}`);
  }
);

promise.then(
  (res) => {
    console.log(`onFulfilled 2`);
  },
  (err) => {
    console.log(`onRejected 2`);
  }
);

// 输出:
// onFulfilled 成功
// onFulfilled 2
const MyPromise = require("./myPromise");

const promise = new MyPromise((resolve, reject) => {
  resolve("成功");
});

promise.then(
  (res) => {
    console.log(`onFulfilled ${res}`);
  },
  (err) => {
    console.log(`onRejected ${err}`);
  }
);

promise.then(
  (res) => {
    console.log(`onFulfilled 2`);
  },
  (err) => {
    console.log(`onRejected 2`);
  }
);

// 输出:
// onFulfilled 成功
// onFulfilled 2
js
const MyPromise = require("./myPromise");

const promise = new MyPromise((resolve, reject) => {
  setTimeout(() => {
    reject("失败");
  });
});

promise.then(
  (res) => {
    console.log(`onFulfilled ${res}`);
  },
  (err) => {
    console.log(`onRejected ${err}`);
  }
);

promise.then(
  (res) => {
    console.log(`onFulfilled 2`);
  },
  (err) => {
    console.log(`onRejected 2`);
  }
);

// 输出:
// onFulfilled 2
const MyPromise = require("./myPromise");

const promise = new MyPromise((resolve, reject) => {
  setTimeout(() => {
    reject("失败");
  });
});

promise.then(
  (res) => {
    console.log(`onFulfilled ${res}`);
  },
  (err) => {
    console.log(`onRejected ${err}`);
  }
);

promise.then(
  (res) => {
    console.log(`onFulfilled 2`);
  },
  (err) => {
    console.log(`onRejected 2`);
  }
);

// 输出:
// onFulfilled 2

可以发现,当任务为同步的时候,是可以按then的调用顺序依次执行的,但是异步resolve的时候,却不可以了。

  • 原因在于:
    • 当同步的时候,promise的状态已经是FULFILLED了,当第二个then任务的时候,会直接继续执行FULFILLED状态的逻辑。
    • 而异步resolve/reject的时候,由于之前使用的是onFulfilledCallback/onRejectedCallback存储回调任务,但是由于使用的是单个变量,而第二个then会覆盖第一个then的回调函数,在第二次宏任务队列的时候,该回调函数才会被调用。
  • 解决方法:
    • 究其原因,就是onCallback的数据结构采用的不对,可以使用队列存储所有的回调函数,当resolve/reject的时候,按顺序出队并且进行调用即可。
js
// MyPromise.js 
// ...
class MyPromise {
  // ...

  // 存储成功/失败的回调函数
  onFulfilledCallbackQueue = new Array(); 
  onRejectedCallbackQueue = new Array(); 

  resolve = (res) => {
    // 如果成功且状态为PENDING
    if (this.status === PENDING) {
      this.status = FULFILLED;
      this.res = res;
      // 如果有成功的回调函数就执行  
      while (this.onFulfilledCallbackQueue.length > 0) { 
        this.onFulfilledCallbackQueue.shift()(res); 
      } 
    }
  };
  reject = (err) => {
    if (this.status === PENDING) {
      this.status = REJECTED;
      this.err = err;
      // 如果有失败的回调函数就执行  
      while (this.onRejectedCallbackQueue.length > 0) { 
        this.onRejectedCallbackQueue.shift()(err); 
      } 
    }
  };

  then(onFulfilled, onRejected) {
    if (this.status === FULFILLED) {
      onFulfilled(this.res);
    } else if (this.status === REJECTED) {
      onRejected(this.err);
    } else if (this.status === PENDING) { 
      this.onFulfilledCallbackQueue.push(onFulfilled); 
      this.onRejectedCallbackQueue.push(onRejected); 
    } 
  }
}

// 此时,输出可以按then的调用顺序执行 
// MyPromise.js 
// ...
class MyPromise {
  // ...

  // 存储成功/失败的回调函数
  onFulfilledCallbackQueue = new Array(); 
  onRejectedCallbackQueue = new Array(); 

  resolve = (res) => {
    // 如果成功且状态为PENDING
    if (this.status === PENDING) {
      this.status = FULFILLED;
      this.res = res;
      // 如果有成功的回调函数就执行  
      while (this.onFulfilledCallbackQueue.length > 0) { 
        this.onFulfilledCallbackQueue.shift()(res); 
      } 
    }
  };
  reject = (err) => {
    if (this.status === PENDING) {
      this.status = REJECTED;
      this.err = err;
      // 如果有失败的回调函数就执行  
      while (this.onRejectedCallbackQueue.length > 0) { 
        this.onRejectedCallbackQueue.shift()(err); 
      } 
    }
  };

  then(onFulfilled, onRejected) {
    if (this.status === FULFILLED) {
      onFulfilled(this.res);
    } else if (this.status === REJECTED) {
      onRejected(this.err);
    } else if (this.status === PENDING) { 
      this.onFulfilledCallbackQueue.push(onFulfilled); 
      this.onRejectedCallbackQueue.push(onRejected); 
    } 
  }
}

// 此时,输出可以按then的调用顺序执行 

链式调用then

DANGER

Node环境下输出结果有问题。

TIP

想要实现链式调用then,就需要每次调用后,都返回一个含有then方法的,在这里需要每次调用后返回一个MyPromise对象,并且需要判断新对象的状态。

1. 可链式调用

js
// MyPromise.js 
// ...
class MyPromise {
    // ...
    then(onFulfilled, onRejected) { 
        return new MyPromise((resolve, reject) => { 
          if (this.status === FULFILLED) {
            onFulfilled(this.res);
          } else if (this.status === REJECTED) {
            onRejected(this.err);
          } else if (this.status === PENDING) {
            this.onFulfilledCallbackQueue.push(onFulfilled);
            this.onRejectedCallbackQueue.push(onRejected);
          }
        }); 
    } 
}

promise = new MyPromise((resolve, reject)=>{setTimeout(()=>{resolve(1);});}); 
promise.then((res)=>{console.log(res); return 2;}).then((res)=>{console.log(res);}) 
// 已经能够执行,但是没有调用第二个then的方法  
// 输出:1 
// MyPromise.js 
// ...
class MyPromise {
    // ...
    then(onFulfilled, onRejected) { 
        return new MyPromise((resolve, reject) => { 
          if (this.status === FULFILLED) {
            onFulfilled(this.res);
          } else if (this.status === REJECTED) {
            onRejected(this.err);
          } else if (this.status === PENDING) {
            this.onFulfilledCallbackQueue.push(onFulfilled);
            this.onRejectedCallbackQueue.push(onRejected);
          }
        }); 
    } 
}

promise = new MyPromise((resolve, reject)=>{setTimeout(()=>{resolve(1);});}); 
promise.then((res)=>{console.log(res); return 2;}).then((res)=>{console.log(res);}) 
// 已经能够执行,但是没有调用第二个then的方法  
// 输出:1 

2. 处理前一个then 的返回值(值为非Promise

js
// MyPromise.js 
// ...
class MyPromise {
    // ...
    then(onFulfilled, onRejected) {
        return new MyPromise((resolve, reject) => {
          if (this.status === FULFILLED) {
            // 获取onFulfilled的返回值 
            const x = onFulfilled(this.res); 
            resolve(x); 
          } else if (this.status === REJECTED) {
            onRejected(this.err);
          } else if (this.status === PENDING) {
            this.onFulfilledCallbackQueue.push(onFulfilled);
            this.onRejectedCallbackQueue.push(onRejected);
          }
        });
    }
}

promise = new MyPromise((resolve, reject)=>{setTimeout(()=>{resolve(1);});}); 
promise.then((res)=>{console.log(res); return 2;}).then((res)=>{console.log(res);}) 
// 输出:1 2 
// MyPromise.js 
// ...
class MyPromise {
    // ...
    then(onFulfilled, onRejected) {
        return new MyPromise((resolve, reject) => {
          if (this.status === FULFILLED) {
            // 获取onFulfilled的返回值 
            const x = onFulfilled(this.res); 
            resolve(x); 
          } else if (this.status === REJECTED) {
            onRejected(this.err);
          } else if (this.status === PENDING) {
            this.onFulfilledCallbackQueue.push(onFulfilled);
            this.onRejectedCallbackQueue.push(onRejected);
          }
        });
    }
}

promise = new MyPromise((resolve, reject)=>{setTimeout(()=>{resolve(1);});}); 
promise.then((res)=>{console.log(res); return 2;}).then((res)=>{console.log(res);}) 
// 输出:1 2 

3. 值为Promise的情况

TIP

如果在 then 方法中返回一个新的 Promise 对象,那么下一个 then 方法会等待这个新的 Promise 对象完成,并且会将其结果作为参数传递给下一个 then 方法。

js
// MyPromise.js 
// ...
class MyPromise {
    // ...
    then(onFulfilled, onRejected) {
        return new MyPromise((resolve, reject) => {
          if (this.status === FULFILLED) {
            const x = onFulfilled(this.res); 
            if(x instanceof MyPromise) { 
                // 如果x是MyPromise类,则等待x执行完后将结果作为下一个then的参数 
                x.then(resolve, reject); 
            } else { 
               resolve(x); 
            } 
          } else if (this.status === REJECTED) {
            onRejected(this.err);
          } else if (this.status === PENDING) {
            this.onFulfilledCallbackQueue.push(onFulfilled);
            this.onRejectedCallbackQueue.push(onRejected);
          }
        });
    }
}

promise = new MyPromise((resolve, reject)=>{setTimeout(()=>{resolve(1);});}); 
promise.then((res)=>{console.log(res); return new MyPromise((resolve)=>{resolve(2);});}).then((res)=>{console.log(res);}); 
// 输出:1 2 
// MyPromise.js 
// ...
class MyPromise {
    // ...
    then(onFulfilled, onRejected) {
        return new MyPromise((resolve, reject) => {
          if (this.status === FULFILLED) {
            const x = onFulfilled(this.res); 
            if(x instanceof MyPromise) { 
                // 如果x是MyPromise类,则等待x执行完后将结果作为下一个then的参数 
                x.then(resolve, reject); 
            } else { 
               resolve(x); 
            } 
          } else if (this.status === REJECTED) {
            onRejected(this.err);
          } else if (this.status === PENDING) {
            this.onFulfilledCallbackQueue.push(onFulfilled);
            this.onRejectedCallbackQueue.push(onRejected);
          }
        });
    }
}

promise = new MyPromise((resolve, reject)=>{setTimeout(()=>{resolve(1);});}); 
promise.then((res)=>{console.log(res); return new MyPromise((resolve)=>{resolve(2);});}).then((res)=>{console.log(res);}); 
// 输出:1 2 

4. 返回值为本身

WARNING

Promise中,如果then返回Promise实例自身的话会报错。

js
const promise = new Promise((resolve)=>{resolve(1)});
const p1 = promise.then(()=>{return p1;});

// Uncaught (in promise) TypeError: Chaining cycle detected for promise #<Promise> 
const promise = new Promise((resolve)=>{resolve(1)});
const p1 = promise.then(()=>{return p1;});

// Uncaught (in promise) TypeError: Chaining cycle detected for promise #<Promise> 

MyPromise中,如果then返回MyPromise实例会怎么样呢?

js
const promise = new MyPromise((resolve)=>{resolve(1)});
const p1 = promise.then(()=>{return p1;});

// Uncaught ReferenceError: p1 is not defined 
const promise = new MyPromise((resolve)=>{resolve(1)});
const p1 = promise.then(()=>{return p1;});

// Uncaught ReferenceError: p1 is not defined 

为什么会出现p1 not defined的情况呢,这是因为:在return p1的时候,return new MyPromise尚未执行成功,此时自然是没有p1的。

  • return new MyPromise后,再执行内部的方法

    可以将then内的逻辑变为一个微任务,这个微任务return后再执行,考虑使用queueMicrotask API实现。

    js
    // MyPromise.js 
    // ...
    class MyPromise {
        // ...
        then(onFulfilled, onRejected) {
        return new MyPromise((resolve, reject) => {
          if (this.status === FULFILLED) {
            queueMicrotask(() => { 
              const x = onFulfilled(this.res);
              if (x instanceof MyPromise) {
                x.then(resolve, reject);
              } else {
                resolve(x);
              }
            });
          } else if (this.status === REJECTED) {
            onRejected(this.err);
          } else if (this.status === PENDING) {
            this.onFulfilledCallbackQueue.push(onFulfilled);
            this.onRejectedCallbackQueue.push(onRejected);
          }
        });
      }
    }
    // MyPromise.js 
    // ...
    class MyPromise {
        // ...
        then(onFulfilled, onRejected) {
        return new MyPromise((resolve, reject) => {
          if (this.status === FULFILLED) {
            queueMicrotask(() => { 
              const x = onFulfilled(this.res);
              if (x instanceof MyPromise) {
                x.then(resolve, reject);
              } else {
                resolve(x);
              }
            });
          } else if (this.status === REJECTED) {
            onRejected(this.err);
          } else if (this.status === PENDING) {
            this.onFulfilledCallbackQueue.push(onFulfilled);
            this.onRejectedCallbackQueue.push(onRejected);
          }
        });
      }
    }
  • 判断返回值是否为自身,如果是,则抛出错误Type Error: ...

    js
    // MyPromise.js 
    // ...
    class MyPromise {
        // ...
        then(onFulfilled, onRejected) {
        const promise2 = new MyPromise((resolve, reject) => { 
          if (this.status === FULFILLED) {
            queueMicrotask(() => {
              const x = onFulfilled(this.res);
              if (x === promise2) { 
                return reject( 
                  new TypeError("Chaining cycle detected for promise #<Promise>")
                );
              }
              if (x instanceof MyPromise) {
                x.then(resolve, reject);
              } else {
                resolve(x);
              }
            });
          } else if (this.status === REJECTED) {
            onRejected(this.err);
          } else if (this.status === PENDING) {
            this.onFulfilledCallbackQueue.push(onFulfilled);
            this.onRejectedCallbackQueue.push(onRejected);
          }
        });
        return promise2;
      }
    }
    
    const promise = new MyPromise((res)=>res(1)); 
    const p1 = promise.then(()=>p1);
    p1.then(console.log,console.error);
    // TypeError: Chaining cycle detected for promise #<Promise> 
    // MyPromise.js 
    // ...
    class MyPromise {
        // ...
        then(onFulfilled, onRejected) {
        const promise2 = new MyPromise((resolve, reject) => { 
          if (this.status === FULFILLED) {
            queueMicrotask(() => {
              const x = onFulfilled(this.res);
              if (x === promise2) { 
                return reject( 
                  new TypeError("Chaining cycle detected for promise #<Promise>")
                );
              }
              if (x instanceof MyPromise) {
                x.then(resolve, reject);
              } else {
                resolve(x);
              }
            });
          } else if (this.status === REJECTED) {
            onRejected(this.err);
          } else if (this.status === PENDING) {
            this.onFulfilledCallbackQueue.push(onFulfilled);
            this.onRejectedCallbackQueue.push(onRejected);
          }
        });
        return promise2;
      }
    }
    
    const promise = new MyPromise((res)=>res(1)); 
    const p1 = promise.then(()=>p1);
    p1.then(console.log,console.error);
    // TypeError: Chaining cycle detected for promise #<Promise> 

捕获报错转为rejected状态

1. 执行器有错误捕获

js
// MyPromise.js 
class MyPromise {
    constructor(executor) {
        try { 
          executor(this.resolve, this.reject);
        } catch (err) {
          this.reject(err);
        }
    }
}

const promise = new MyPromise((resolve, reject) => { 
    throw new Error('a new error!');
}); 
promise.then(console.log,console.error); // Error: a new error!
// MyPromise.js 
class MyPromise {
    constructor(executor) {
        try { 
          executor(this.resolve, this.reject);
        } catch (err) {
          this.reject(err);
        }
    }
}

const promise = new MyPromise((resolve, reject) => { 
    throw new Error('a new error!');
}); 
promise.then(console.log,console.error); // Error: a new error!

2. then执行有错误并捕获

js
// MyPromise.js 
// ...
class MyPromise {
    // ...
    then(onFulfilled, onRejected) {
    const promise2 = new MyPromise((resolve, reject) => { 
      if (this.status === FULFILLED) {
      	queueMicrotask(() => { 
          try{
            const x = onFulfilled(this.res);
            if (x === promise2) {
              return reject(
                new TypeError("Chaining cycle detected for promise #<Promise>")
              );
            }
            if (x instanceof MyPromise) {
              x.then(resolve, reject);
            } else {
              resolve(x);
            }
          } catch (err) {
            reject(err);
          }
        });
      } else if (this.status === REJECTED) {
        onRejected(this.err);
      } else if (this.status === PENDING) {
        this.onFulfilledCallbackQueue.push(onFulfilled);
        this.onRejectedCallbackQueue.push(onRejected);
      }
    });
    return promise2;
  }
}

const promise = new MyPromise((res, rej)=>res(1)); 
promise.then((res)=>{console.log(res);throw new Error('another new error!')}).then(console.log, console.error);
// 1
// TypeError: Chaining cycle detected for promise #<Promise> 
// MyPromise.js 
// ...
class MyPromise {
    // ...
    then(onFulfilled, onRejected) {
    const promise2 = new MyPromise((resolve, reject) => { 
      if (this.status === FULFILLED) {
      	queueMicrotask(() => { 
          try{
            const x = onFulfilled(this.res);
            if (x === promise2) {
              return reject(
                new TypeError("Chaining cycle detected for promise #<Promise>")
              );
            }
            if (x instanceof MyPromise) {
              x.then(resolve, reject);
            } else {
              resolve(x);
            }
          } catch (err) {
            reject(err);
          }
        });
      } else if (this.status === REJECTED) {
        onRejected(this.err);
      } else if (this.status === PENDING) {
        this.onFulfilledCallbackQueue.push(onFulfilled);
        this.onRejectedCallbackQueue.push(onRejected);
      }
    });
    return promise2;
  }
}

const promise = new MyPromise((res, rej)=>res(1)); 
promise.then((res)=>{console.log(res);throw new Error('another new error!')}).then(console.log, console.error);
// 1
// TypeError: Chaining cycle detected for promise #<Promise> 

参数onFulfilled/onRejected可选

TIP

onFulfilled/onRejected添加默认值即可。

  • onFulfilled不存在,那么默认为将已有结果返回给下一个then

  • onRejected不存在,那么默认为将已有的错误继续抛出给下一个then

js
// MyPromise.js 
// ...
class MyPromise {
    // ...
    then(onFulfilled, onRejected) {
        onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : res => res;
        onRejected = typeof onRejected === 'function' ? onRejected : err => { throw err; };
    	const promise2 = new MyPromise((resolve, reject) => { 
      	// ...
        }
  	}
}

const promise = new MyPromise((res, rej)=>res(1)); 
const promise2 = new MyPromise((res,rej)=>{ throw new Error('3rd error!'); });
promise.then().then((res)=>{console.log(res);}); // 1
promise2.then().then(console.log, console.error); // Error: 3rd error!
// MyPromise.js 
// ...
class MyPromise {
    // ...
    then(onFulfilled, onRejected) {
        onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : res => res;
        onRejected = typeof onRejected === 'function' ? onRejected : err => { throw err; };
    	const promise2 = new MyPromise((resolve, reject) => { 
      	// ...
        }
  	}
}

const promise = new MyPromise((res, rej)=>res(1)); 
const promise2 = new MyPromise((res,rej)=>{ throw new Error('3rd error!'); });
promise.then().then((res)=>{console.log(res);}); // 1
promise2.then().then(console.log, console.error); // Error: 3rd error!

实现Promise.resolve()/Promise.reject()静态方法

js
// MyPromise.js
// ...
class MyPromise {
    // ...
    static resolve(value) {
        if(value instanceof MyPromise) {
            return value;
        } else {
            return new MyPromise((resolve) => {
                resolve(value);
            })
        }
    }
    static reject(err) {
        return new MyPromise((_resolve, reject) => {
            reject(err);
        })
    }
}

MyPromise.resolve(1); // MyPromise {res: 1, status: 'fulfilled', ...}
MyPromise.resolve(new MyPromise((resolve)=>{resolve(2);})); // MyPromise {res: 2, status: 'fulfilled', ...}
MyPromise.reject(new Error(3)); // MyPromise {err: 3, status: 'rejected', ...}
// MyPromise.js
// ...
class MyPromise {
    // ...
    static resolve(value) {
        if(value instanceof MyPromise) {
            return value;
        } else {
            return new MyPromise((resolve) => {
                resolve(value);
            })
        }
    }
    static reject(err) {
        return new MyPromise((_resolve, reject) => {
            reject(err);
        })
    }
}

MyPromise.resolve(1); // MyPromise {res: 1, status: 'fulfilled', ...}
MyPromise.resolve(new MyPromise((resolve)=>{resolve(2);})); // MyPromise {res: 2, status: 'fulfilled', ...}
MyPromise.reject(new Error(3)); // MyPromise {err: 3, status: 'rejected', ...}
完整代码
js
// MyPromise.js
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";

class MyPromise {
  constructor(executor) {
    try {
      executor(this.resolve, this.reject);
    } catch (err) {
      this.reject(err);
    }
  }

  static resolve(value) {
    if (value instanceof MyPromise) {
      return value;
    } else {
      return new MyPromise((resolve) => {
        resolve(value);
      });
    }
  }

  static reject(err) {
    return new MyPromise((_resolve, reject) => {
      reject(err);
    });
  }

  // 存储成功的参数
  res = null;
  // 存储失败的参数
  err = null;
  // 初始状态
  status = PENDING;

  // 存储成功/失败的回调函数
  onFulfilledCallbackQueue = new Array();
  onRejectedCallbackQueue = new Array();

  resolve = (res) => {
    // 如果成功且状态为PENDING
    if (this.status === PENDING) {
      this.status = FULFILLED;
      this.res = res;
      // 如果有成功的回调函数就执行
      while (this.onFulfilledCallbackQueue.length > 0) {
        this.onFulfilledCallbackQueue.shift()(res);
      }
    }
  };
  reject = (err) => {
    if (this.status === PENDING) {
      this.status = REJECTED;
      this.err = err;
      // 如果有失败的回调函数就执行
      while (this.onRejectedCallbackQueue.length > 0) {
        this.onRejectedCallbackQueue.shift()(err);
      }
    }
  };

  then(onFulfilled, onRejected) {
    onFulfilled =
      typeof onFulfilled === "function" ? onFulfilled : (res) => res;
    onRejected =
      typeof onRejected === "function"
        ? onRejected
        : (err) => {
            throw err;
          };
    const promise2 = new MyPromise((resolve, reject) => {
      if (this.status === FULFILLED) {
        queueMicrotask(() => {
          try {
            const x = onFulfilled(this.res);
            if (x === promise2) {
              return reject(
                new TypeError("Chaining cycle detected for promise #<Promise>")
              );
            }
            if (x instanceof MyPromise) {
              x.then(resolve, reject);
            } else {
              resolve(x);
            }
          } catch (err) {
            reject(err);
          }
        });
      } else if (this.status === REJECTED) {
        onRejected(this.err);
      } else if (this.status === PENDING) {
        this.onFulfilledCallbackQueue.push(onFulfilled);
        this.onRejectedCallbackQueue.push(onRejected);
      }
    });
    return promise2;
  }
}

if (typeof module !== "undefined" && module.exports) {
  // 在 Node.js 环境中
  module.exports = MyPromise;
}
// MyPromise.js
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";

class MyPromise {
  constructor(executor) {
    try {
      executor(this.resolve, this.reject);
    } catch (err) {
      this.reject(err);
    }
  }

  static resolve(value) {
    if (value instanceof MyPromise) {
      return value;
    } else {
      return new MyPromise((resolve) => {
        resolve(value);
      });
    }
  }

  static reject(err) {
    return new MyPromise((_resolve, reject) => {
      reject(err);
    });
  }

  // 存储成功的参数
  res = null;
  // 存储失败的参数
  err = null;
  // 初始状态
  status = PENDING;

  // 存储成功/失败的回调函数
  onFulfilledCallbackQueue = new Array();
  onRejectedCallbackQueue = new Array();

  resolve = (res) => {
    // 如果成功且状态为PENDING
    if (this.status === PENDING) {
      this.status = FULFILLED;
      this.res = res;
      // 如果有成功的回调函数就执行
      while (this.onFulfilledCallbackQueue.length > 0) {
        this.onFulfilledCallbackQueue.shift()(res);
      }
    }
  };
  reject = (err) => {
    if (this.status === PENDING) {
      this.status = REJECTED;
      this.err = err;
      // 如果有失败的回调函数就执行
      while (this.onRejectedCallbackQueue.length > 0) {
        this.onRejectedCallbackQueue.shift()(err);
      }
    }
  };

  then(onFulfilled, onRejected) {
    onFulfilled =
      typeof onFulfilled === "function" ? onFulfilled : (res) => res;
    onRejected =
      typeof onRejected === "function"
        ? onRejected
        : (err) => {
            throw err;
          };
    const promise2 = new MyPromise((resolve, reject) => {
      if (this.status === FULFILLED) {
        queueMicrotask(() => {
          try {
            const x = onFulfilled(this.res);
            if (x === promise2) {
              return reject(
                new TypeError("Chaining cycle detected for promise #<Promise>")
              );
            }
            if (x instanceof MyPromise) {
              x.then(resolve, reject);
            } else {
              resolve(x);
            }
          } catch (err) {
            reject(err);
          }
        });
      } else if (this.status === REJECTED) {
        onRejected(this.err);
      } else if (this.status === PENDING) {
        this.onFulfilledCallbackQueue.push(onFulfilled);
        this.onRejectedCallbackQueue.push(onRejected);
      }
    });
    return promise2;
  }
}

if (typeof module !== "undefined" && module.exports) {
  // 在 Node.js 环境中
  module.exports = MyPromise;
}

Released under the MIT License.