引言
在现代 JavaScript 开发中,异步编程是处理非阻塞操作的关键技术。Promise 对象提供了一种更加优雅的方式来处理异步操作,使得代码更加清晰和易于维护。在本篇博客中,我们将通过手写一个简单的 Promise 类来深入理解其内部机制,这是我们异步编程系列课程的第一课。
Promise 的核心概念
在深入代码之前,让我们先回顾一下 Promise 的核心概念:
- PENDING:Promise 的初始状态,表示异步操作尚未完成。
- FULFILLED:异步操作成功完成,Promise 将进入此状态。
- REJECTED:异步操作失败,Promise 将进入此状态。
这三个状态是 Promise 规范中定义的,它们帮助我们管理和控制异步操作的生命周期。
手写 MyPromise 类
下面是我们第一节课的实践内容,我们将通过手写一个简单的 Promise 类来模拟 Promise 的行为:
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
class MyPromise {
constructor(executor) {
this._state = PENDING; // 初始化状态为 pending
this._value = undefined; // 用于存储异步操作的结果
try {
executor(this._resolve.bind(this), this._reject.bind(this));
} catch (error) {
this._reject(error); // 如果 executor 抛出错误,立即将状态设置为 rejected
}
}
_changeState(newState, value) {
if (this._state !== PENDING) {
return; // 如果状态已经不是 pending,则不进行状态变更
}
this._state = newState; // 改变状态
this._value = value; // 保存异步操作的结果
}
_resolve(data) {
this._changeState(FULFILLED, data); // 异步操作成功,状态变为 fulfilled
console.log('完成', data);
}
_reject(reason) {
this._changeState(REJECTED, reason); // 异步操作失败,状态变为 rejected
console.log('失败', reason);
}
}
const pro = new MyPromise((resolve, reject) => {
throw new Error('5555'); // 模拟异步操作失败
});
console.log(pro); // 输出 Promise 对象的状态和值
代码解析
- 构造函数:在构造函数中,我们初始化 Promise 对象的状态为
PENDING,并尝试执行传入的executor函数。如果executor抛出错误,我们立即调用_reject方法。 - _changeState 方法:这是一个私有方法,用于改变 Promise 的状态。它确保状态的改变是原子操作,并且只在状态为
PENDING时才允许改变状态。 - _resolve 和 _reject 方法:这两个私有方法分别用于在异步操作成功或失败时调用。它们通过调用
_changeState方法来改变状态,并记录相关的值。 - 测试 Promise:在示例中,我们创建了一个
MyPromise实例,并在executor函数中抛出了一个错误。这将导致 Promise 状态变为REJECTED,并打印出错误信息。
结论
通过这第一节课,我们学习了如何手写一个简单的 Promise 类,理解了 Promise 的三种状态以及如何通过代码来控制这些状态。这是我们异步编程系列课程的第一步,为后续更深入的学习打下了坚实的基础。
进一步阅读
希望这节课能够帮助你建立起对 Promise 的基本理解,为后续更深入的学习做好准备。