Skip to content

Promise

手写Promise过程

分析:Promise最重要的有三个状态pending(等待),fufilled(完成),rejected(失败)

接下来我们手一个SimplePromise函数,包括基本的功能:resolve、reject 和 then 方法。

正常我们的Promise使用是这样子的

JS
new Promise(( resolve, reject ) =>{}).then().catch()

接下里我们就一步步手写一个简单的 Promise

第一步:创建基础结构

我们先写一个类,SimplePromise,搭建好基础的Prmise结构

接下来我们分别:定义结构 状态 然后绑定 执行 executor 函数(负责定义异步操作成功或失败的逻辑),把当前函数的resolve和reject作为参数传递给它 定义resolve函数和reject函数,处理成功和失败时候的值和状态

js
class SimplePromise {
  constructor(executor) {
    this.state = 'pending'; // 初始状态
    this.value = undefined; // 成功时的值
    this.reason = undefined; // 失败时的原因

    // 执行传入的函数
    executor(this.resolve.bind(this), this.reject.bind(this));
  }

  resolve(value) {
    // 将状态设置为已完成
    this.state = 'fulfilled';
    this.value = value;
  }

  reject(reason) {
    // 将状态设置为已失败
    this.state = 'rejected';
    this.reason = reason;
  }
}

补充: 上面的constructor函数是类的方法,在new SimplePromise()时会自动调用,不需要额外手动调用

第二步:实现 then 方法

接下来给SimplePromise 添加 then 方法,用于处理成功和失败的回调 这里接着:传入onFulfilled onRejected ,判断状态 成功操作value 失败操作reason

js
 // then方法
  then(onFulfilled, onRejected){
      if(this.status=='fulfilled'){
          onFulfilled(this.value);
      }else if(this.status=='rejected'){
          onRejected(this.reason);
      }
  }

第三步:处理异步情况

我们需要处理异步操作的情况,这样 then 方法可以在状态改变后被正确调用,我们将成功和失败的回调存储在数组中,这里我们依然放入我们的构造函数之中

定义成功回调数组 失败回调数组 resolve 和 reject 的时候处理回调函数数组 then的时候推入函数onFulfilled和onRejected到onResolvedCallbacks和onRejectedCallbacks 数组中

js
constructor(executor) {
  // ... 省略之前的内容
  this.onResolvedCallbacks = []; // 存储成功的回调
  this.onRejectedCallbacks = []; // 存储失败的回调
}

resolve(value) {
  if (this.state === 'pending') {
    this.state = 'fulfilled';
    this.value = value;
    this.onResolvedCallbacks.forEach(callback => callback(value));
  }
}

reject(reason) {
  if (this.state === 'pending') {
    this.state = 'rejected';
    this.reason = reason;
    this.onRejectedCallbacks.forEach(callback => callback(reason));
  }
}

then(onFulfilled, onRejected) {
  if (this.state === 'fulfilled') {
    onFulfilled(this.value);
  } else if (this.state === 'rejected') {
    onRejected(this.reason);
  } else if (this.state === 'pending') {
    this.onResolvedCallbacks.push(() => {
      onFulfilled(this.value);
    });
    this.onRejectedCallbacks.push(() => {
      onRejected(this.reason);
    });
  }
}

补充:

这里我们需要注意的就是:

使用箭头函数将 onRejected(this.value) 封装起来,可以确保这个回调在 Promise 状态变为“拒绝”时才执行,而不是在它被添加到回调数组时立即执行。

因为箭头函数本身并不会立即执行,它的执行时机取决于它如何被调用

在 Promise 的上下文中,箭头函数被定义后,只是被存储在一个数组中,并不会立即执行。

JS
this.onResolvedCallbacks.forEach(callback => callback(value));

在这里作用其实就是 遍历 this.onResolvedCallbacks 数组中的所有回调函数,并对每一个函数调用,传递一个参数 value。

通常发生在 Promise 的状态变为“已解决”(fulfilled)时,用于执行所有注册的回调。

第四步:添加错误处理

接下来我们尝试在回调中捕获异常,避免我们有未处理的错误

利用try carch 捕获正常异常信息 然后调用resolve 或者 reject 方法

js
 // then方法
  then(onFulfilled, onRejected) {
      //2 捕获正常异常信息
      const handleFulfilled=()=>{
          try{
              const result = onFulfilled(this.value);
              resolve(result);
          }catch(error){
              reject(error)
          }
      } 
      const handleRejected=()=>{
          try{
              const result = onRejected(this.reason);
              resolve(reason);
          }catch(error){
              reject(error)
          }
      }

      // 1
      if (this.status == 'fulfilled') {
          // onFulfilled(this.value);
          handleFulfilled() //3 
      } else if (this.status == 'rejected') {
          // onRejected(this.reason);
          handleRejected() //3 
      } else if (this.status == 'pending') {

          // this.onFulfilledCallbacks.push(() => {
          //     onFulfilled(this.value);
          // });
          // this.onRejectedCallbacs.push(() => {
          //     onRejected(this.value);
          // });

          this.onResolvedCallbacks.push(handleFulfilled);
          this.onRejectedCallbacks.push(handleRejected);
      }
}

最终完整版实现

JS
class SimplePromise {
  constructor(executor) {
    this.state = 'pending';
    this.value = undefined;
    this.reason = undefined;
    this.onResolvedCallbacks = [];
    this.onRejectedCallbacks = [];

    const resolve = (value) => {
      if (this.state === 'pending') {
        this.state = 'fulfilled';
        this.value = value;
        this.onResolvedCallbacks.forEach(callback => callback(value));
      }
    };

    const reject = (reason) => {
      if (this.state === 'pending') {
        this.state = 'rejected';
        this.reason = reason;
        this.onRejectedCallbacks.forEach(callback => callback(reason));
      }
    };

   try {
      executor(resolve, reject);
    } catch (error) {
      reject(error);
    }
  }

  then(onFulfilled, onRejected) {
    return new SimplePromise((resolve, reject) => {
      const handleFulfilled = () => {
        try {
          const result = onFulfilled(this.value);
          resolve(result);
        } catch (error) {
          reject(error);
        }
      };

      const handleRejected = () => {
        try {
          const result = onRejected(this.reason);
          resolve(result);
        } catch (error) {
          reject(error);
        }
      };

      if (this.state === 'fulfilled') {
        handleFulfilled();
      } else if (this.state === 'rejected') {
        handleRejected();
      } else if (this.state === 'pending') {
        this.onResolvedCallbacks.push(handleFulfilled);
        this.onRejectedCallbacks.push(handleRejected);
      }
    });
  }
}

// 使用示例
const promise = new SimplePromise((resolve, reject) => {
  setTimeout(() => {
    resolve("成功!");
  }, 1000);
});

promise.then(result => {
  console.log(result); // "成功!"
}).catch(error => {
  console.error(error);
});

Released under the MIT License.