Promise实现原理

110次阅读
没有评论

前言

在编程中,Promise 是一种常见的编程模式,它有效的帮助我们解决回调地狱问题。使我们能更优雅的编程,提高代码可读性和维护性。

我以前只会使用 Promise,并不知道它的实现源码,无法更好的理解 Promise。通过学习视频和查阅资料,深刻的理解该方法的源码。现在我将记录 Promise 源码实现的过程。

【实现 Promise 以下方法】

  • resolve
  • reject
  • then
  • catch
  • all
  • race

Promise 的三种状态

Promise 有 pending、fulfilled 和 rejected 三种状态,其中初始状态状态为 pending。

// 等待中
const PROMISE_PENDING_STATE = "pending";
// 成功
const PROMISE_FULFILLED_STATE = "fulfilled";
// 失败
const PROMISE_REJECTED_STATE = "rejected";

Promise 类方法

我们在调用创建 Promise 实例的时候,需要传入一个执行函数,这个函数接受两个参数,resolve 和 reject。通过 resolve 函数将 Promise 的状态由 pending 改为 fulfilled,通过 reject 函数将 Promise 的状态由 pending 改为 rejected。

下面我们定义 Promise 类方法,PromiseState 属性为 Promise 的状态,PromiseResult 属性存储的是 Promise 成功数据或失败的信息。

class Promise {
  constructor(execute) {
    this.PromiseState = PROMISE_PENDING_STATE;
    this.PromiseResult = undefined;

    // 通过bind改变this指向
    execute(this.resolve.bind(this), this.reject.bind(this));
  }
}

实现 resolve,reject

Promise 的状态转换是不可逆的,一旦由 pending -> fulfilled 或 pending -> rejected 就不能再改变 Promise 的状态。

resolve(result) {
  // 当PromiseState为初始状态时,才允许修改
  if (this.PromiseState === PROMISE_PENDING_STATE) {
    this.PromiseState = PROMISE_FULFILLED_STATE;
    this.PromiseResult = result;
  }
}

reject(reason) {
  // 当PromiseState为初始状态时,才允许修改
  if (this.PromiseState === PROMISE_PENDING_STATE) {
    this.PromiseState = PROMISE_REJECTED_STATE;
    this.PromiseResult = reason;
  }
}

执行函数抛出错误的时,Promise 的状态也将由 pending -> rejected, 需要通过 try catch 捕获错误。

class Promise {
  constructor(execute) {
    // ...
    try {
      execute(this.resolve.bind(this), this.reject.bind(this));
    } catch (error) {
      this.reject(error);
    }
  }
}

使用

const p1 = new Promise((resolve, reject) => {
  resolve("success");
});

console.dir(p1);

Promise实现原理

const p1 = new Promise((resolve, reject) => {
  reject("error");
});

console.dir(p1);

Promise实现原理

同步的 then 方法

当前实现只支持同步修改 Promise 状态。稍后再实现异步修改 Promise 状态。

then 用于处理 Promise 的结果,当 Promise 的结果确定后,then()方法会被调用。并且可以传入两个回调函数来处理 Promise 的结果。如果 Promise 的结果是 resolve,第一个调用函数会被调用并传入 resolve 的结果作为参数;如果 Promise 的结果是 reject,第二个函数会被调用并传入 reject 的错误信息作为参数。

then 方法返回一个新的 Promise,该 Promise 的状态由回调函数决定。如果回调函数返回的是一个 Promise 对象,那么新 Promise 的状态将与该 Promise 对象的状态相同。如果回调函数抛出错误,那么新 Promise 的状态将为 rejected,需要通过 try catch 捕获错误。

then(onResolved, onRejected) {
 return new Promise((resolve, reject) => {
  // 成功
  if (this.PromiseState === PROMISE_FULFILLED_STATE) {
    try {
      const result = onResolved(this.PromiseResult);
      if (result instanceof Promise) {
        result.then(
          (res) => {
            resolve(res);
          },
          (err) => {
            reject(err);
          }
        );
      } else {
        resolve(result);
      }
    } catch (err) {
      reject(err);
    }
  }

  // 失败
  if (this.PromiseState === PROMISE_REJECTED_STATE) {
    try {
      const result = onRejected(this.PromiseResult);
      if (result instanceof Promise) {
        result.then(
          (res) => {
            resolve(res);
          },
          (err) => {
            reject(err);
          }
        );
      } else {
        resolve(result);
      }
    } catch (err) {
      reject(err);
    }
  }
 })
}

由于处理成功和失败的回调做的事情都一样,只有执行的函数不一样,可以将处理成功和失败的回调封装为一个公共方法,以便重复使用。

then(onResolved, onRejected) {
 return new Promise((resolve, reject) => {
  // 封装的公共方法
  const callback = (fn) => {
    try {
      const result = fn(this.PromiseResult);
      if (result instanceof Promise) {
        result.then(
          (res) => {
            resolve(res);
          },
          (err) => {
            reject(err);
          }
        );
      } else {
        resolve(result);
      }
    } catch (err) {
      reject(err);
    }
  };
  // 成功
  if (this.PromiseState === PROMISE_FULFILLED_STATE) {
    callback(onResolve);
  }

  // 失败
  if (this.PromiseState === PROMISE_REJECTED_STATE) {
    callback(onRejected);
  }
 })
}

使用

const p1 = new Promise((resolve, reject) => {
  resolve("success");
}).then(
  (res) => {
    console.log(res); // success
    return "success----2";
  },
  () => {
    // ....
  }
);

console.dir(p1);

Promise实现原理

const p1 = new Promise((resolve, reject) => {
  reject("error");
}).then(
  () => {
    // ....
  },
  (err) => {
    console.log(err); // error
    return "error---2";
  }
);

console.dir(p1);

Promise实现原理

异步的 then 方法

上面代码都是通过同步修改 Promise 的状态,原生的 Promise 是支持异步修改 Promise 状态的,我们需要在 Promise 类中定义一个 callbacks 属性,用于存储当 Promise 状态改变后需要执行的回调方法。当 Promise 状态由 pending -> fulfilled 或 pending -> rejected 时,循环执行 callbacks 存储的回调方法,使其支持异步修改 Promise 的状态。

Promise 类添加 callbacks 属性

class Promise {
  constructor(execute) {
    // ...
    this.callbacks = [];
  }
}

then 方法处理异步回调

then(onResolved, onRejected) {
 return new Promise((resolve, reject) => {
  // ....
  // 等待中
  if (this.PromiseState === PROMISE_PENDING_STATE) {
    // 添加异步回调
    this.callbacks.push({
      onResolved: () => {
        callback(onResolved);
      },
      onRejected: () => {
        callback(onRejected);
      },
    });
  }
 })
}

resolve,reject 方法异步执行

resolve(result) {
  if (this.PromiseState === PROMISE_PENDING_STATE) {
    // ...
    // 循环执行成功回调
    this.callbacks.forEach((cb) => {
      cb.onResolved(this.PromiseResult);
    });
  }
}

reject(reason) {
  if (this.PromiseState === PROMISE_PENDING_STATE) {
    // ...
    // 循环执行失败回调
    this.callbacks.forEach((cb) => {
      cb.onRejected(this.PromiseResult);
    });
  }
}

使用

const p1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("success");
  }, 2000);
}).then(
  (res) => {
    console.log(res); // 2秒后输出success
    return "success----2";
  },
  () => {
    // ...
  }
);
const p1 = new Promise((resolve, reject) => {
  reject("error");
}).then(
  () => {
    // ....
  },
  (err) => {
    console.log(err); // 2秒后输出error
    return "error---2";
  }
);

优化 then 方法

在 Promise 中,then 方法是异步执行的。为了确保 then 方法在同步任务完成后执行,我们可以通过 setTimeout 方法将 then 方法的执行放到宏任务中执行。这样,在同步任务执行完毕后,then 方法才会被调用。

未使用 setTimeout 优化

new Promise((resolve, reject) => {
  console.log(1);
  resolve("success");
}).then(
  (res) => {
    console.log(3);
    return "success----2";
  },
  () => {
    // ...
  }
);

console.log(2);

Promise实现原理

使用 setTimeout 优化

then 方法

then(onResolved, onRejected) {
   return new Promise((resolve, reject) => {
    // 成功
    if (this.PromiseState === PROMISE_FULFILLED_STATE) {
      setTimeout(() => {
        callback(onResolved);
      });
    }

    // 失败
    if (this.PromiseState === PROMISE_REJECTED_STATE) {
      setTimeout(() => {
        callback(onRejected);
      });
    }
   })
}

resolve,reject 方法

resolve(result) {
  if (this.PromiseState === PROMISE_PENDING_STATE) {
    // ...

    setTimeout(() => {
      this.callbacks.forEach((cb) => {
        // ...
      });
    });
  }
}

reject(reason) {
  if (this.PromiseState === PROMISE_PENDING_STATE) {
    // ...

    setTimeout(() => {
      this.callbacks.forEach((cb) => {
        // ...
      });
    });
  }
}

结果:

new Promise((resolve, reject) => {
  console.log(1);
  resolve("success");
}).then(
  (res) => {
    console.log(3);
    return "success----2";
  },
  () => {
    // ...
  }
);

console.log(2);

Promise实现原理

onResolved,onRejected 可选
Promise 中的 then 方法回调参数都是可选的,当调用 then 方法未传参数时,需要给默认值。

then(onResolved, onRejected) {
  if (typeof onResolved !== "function") {
    onResolved = (result) => {
      return result;
    };
  }
  if (typeof onRejected !== "function") {
    onRejected = (reason) => {
      throw reason;
    };
  }
  // ...
}

catch 方法

当返回的 Promise 状态为 reject 时,可以使用 catch 方法捕获错误信息。

catch(onRejected) {
  return this.then(null, onRejected);
}

Promise.resolve,Promise.reject

Promise.resolve 方法返回一个 Promise 对象,该 Promise 的状态由回调函数决定。如果回调函数返回的是一个 Promise 对象,那么新 Promise 的状态将与该 Promise 对象的状态相同。如果回调函数抛出错误,那么新 Promise 的状态将为 rejected,需要通过 try catch 捕获错误。

Promise.reject 方法返回一个 Promise 对象,该 Promise 的状态为 rejected。


static resolve(result) {
  return new Promise((resolve, reject) => {
    if (result instanceof Promise) {
      result.then(
        (res) => {
          resolve(res);
        },
        (err) => {
          reject(err);
        }
      );
    } else {
      resolve(result);
    }
  });
}

static reject(result) {
  return new Promise((resolve, reject) => {
    reject(result);
  });
}

使用

const p1 = Promise.resolve(100);
console.dir(p1);

Promise实现原理

const p1 = Promise.rejected(0);
console.dir(p1);

Promise实现原理

Promise.all

Promise.all 方法接收一个 Promise 数组,返回一个新的 Promise 对象。该 Promise 对象的状态由数组中的元素决定。如果数组中所有元素的 PromiseState 状态都为 fulfilled,则 Promise 对象的状态为 fulfilled,PromiseResult 为数组中所有成功数据的集合。如果数组中至少有一个元素的 PromiseState 为 rejected,则 Promise 对象的状态为 rejected,PromiseResult 为该元素对应的错误信息。

为了解决异步操作的问题,我们定义 result 数组,用于接收 Promise 数组中元素成功的集合,等待数组中的所有 Promise 都完成并返回一个结果数组。

为了确保结果数组中的元素顺序,可以在循环中使用索引来指定成功 Promise 成功结果在 result 数组中的下标位置。

static all(promises) {
  let result = [];
  let count = 0;
  return new Promise((resolve, reject) => {
    for (let i = 0; i length; i++) {
      promises[i].then(
        (res) => {
          result[i] = res;
          count++;
          if (count === promises.length) {
            resolve(result);
          }
        },
        (reason) => {
          reject(reason);
        }
      );
    }
  });
}

Promise.race

Promise.race 方法接收一个 Promise 数组,返回一个新的 Promise 对象。该 Promise 对象的状态由数组中第一个返回结果的元素决定。

static race(promises) {
  return new Promise((resolve, reject) => {
    for (let i = 0; i length; i++) {
      promises[i].then(
        (res) => {
          resolve(res);
        },
        (reason) => {
          reject(reason);
        }
      );
    }
  });
}

完整代码

const PROMISE_PENDING_STATE = "pending";
const PROMISE_FULFILLED_STATE = "fulfilled";
const PROMISE_REJECTED_STATE = "rejected";

class Promise {
  constructor(execute) {
    this.PromiseState = PROMISE_PENDING_STATE;
    this.PromiseResult = undefined;
    this.callbacks = [];

    try {
      execute(this.resolve.bind(this), this.reject.bind(this));
    } catch (error) {
      this.reject(error);
    }
  }

  resolve(result) {
    if (this.PromiseState === PROMISE_PENDING_STATE) {
      this.PromiseState = PROMISE_FULFILLED_STATE;
      this.PromiseResult = result;

      setTimeout(() => {
        this.callbacks.forEach((cb) => {
          cb.onResolved(this.PromiseResult);
        });
      });
    }
  }

  reject(reason) {
    if (this.PromiseState === PROMISE_PENDING_STATE) {
      this.PromiseState = PROMISE_REJECTED_STATE;
      this.PromiseResult = reason;

      setTimeout(() => {
        this.callbacks.forEach((cb) => {
          cb.onRejected(this.PromiseResult);
        });
      });
    }
  }

  then(onResolved, onRejected) {
    if (typeof onResolved !== "function") {
      onResolved = (result) => {
        return result;
      };
    }
    if (typeof onRejected !== "function") {
      onRejected = (reason) => {
        throw reason;
      };
    }
    return new Promise((resolve, reject) => {
      const callback = (fn) => {
        try {
          const result = fn(this.PromiseResult);
          if (result instanceof Promise) {
            result.then(
              (res) => {
                resolve(res);
              },
              (err) => {
                reject(err);
              }
            );
          } else {
            resolve(result);
          }
        } catch (err) {
          reject(err);
        }
      };

      // 成功
      if (this.PromiseState === PROMISE_FULFILLED_STATE) {
        setTimeout(() => {
          callback(onResolved);
        });
      }

      // 失败
      if (this.PromiseState === PROMISE_REJECTED_STATE) {
        setTimeout(() => {
          callback(onRejected);
        });
      }

      // 等待中
      if (this.PromiseState === PROMISE_PENDING_STATE) {
        this.callbacks.push({
          onResolved: () => {
            callback(onResolved);
          },
          onRejected: () => {
            callback(onRejected);
          },
        });
      }
    });
  }

  catch(onRejected) {
    return this.then(null, onRejected);
  }

  static resolve(result) {
    return new Promise((resolve, reject) => {
      if (result instanceof Promise) {
        result.then(
          (res) => {
            resolve(res);
          },
          (err) => {
            reject(err);
          }
        );
      } else {
        resolve(result);
      }
    });
  }

  static reject(result) {
    return new Promise((resolve, reject) => {
      reject(result);
    });
  }

  static all(promises) {
    let result = [];
    let count = 0;
    return new Promise((resolve, reject) => {
      for (let i = 0; i length; i++) {
        promises[i].then(
          (res) => {
            result[i] = res;
            count++;
            if (count === promises.length) {
              resolve(result);
            }
          },
          (reason) => {
            reject(reason);
          }
        );
      }
    });
  }

  static race(promises) {
    return new Promise((resolve, reject) => {
      for (let i = 0; i length; i++) {
        promises[i].then(
          (res) => {
            resolve(res);
          },
          (reason) => {
            reject(reason);
          }
        );
      }
    });
  }
}

文章来源于互联网:Promise实现原理

正文完
 0
评论(没有评论)