揭开 Promise 之谜:从头开始亲手实现
2024-01-11 03:56:39
前言
在 JavaScript 的汪洋大海中,Promise 就像一艘航海利器,它帮助我们优雅地处理异步操作,避免回调地狱的困扰。今天,我们将抛开抽象,从头开始构建自己的 Promise 实现,深入探究其内部运作机制。
Promise 的前世今生
Promise,一个看似简单的概念,却有着不平凡的身世。它诞生于 ECMAScript 2015 规范中,旨在为异步操作提供一种更优雅、更可控的方式。在 Promise 出现之前,我们只能通过回调函数来处理异步操作,导致代码难以维护和理解。
动手实现 Promise
现在,让我们卷起袖子,开始我们自己的 Promise 实现之旅。
1. 状态管理
Promise 有三个状态:待定(pending)、已完成(fulfilled)和已拒绝(rejected)。我们需要创建三个常量来表示这些状态。
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
2. 执行函数
Promise 在创建时接受一个执行函数作为参数。此函数有两个形参:resolve 和 reject,它们用于改变 Promise 的状态。
class Promise {
constructor(executor) {
this.state = PENDING;
executor(this.resolve.bind(this), this.reject.bind(this));
}
3. 改变状态
resolve 和 reject 方法用于将 Promise 的状态从待定更改为已完成或已拒绝。它们接受一个值作为参数,该值将成为 Promise 的结果。
resolve(value) {
if (this.state !== PENDING) return;
this.state = FULFILLED;
this.result = value;
this.onFulfilled();
}
reject(error) {
if (this.state !== PENDING) return;
this.state = REJECTED;
this.result = error;
this.onRejected();
}
4. 回调队列
为了在 Promise 状态改变后执行回调函数,我们需要维护两个回调队列:onFulfilled 和 onRejected。
onFulfilled() {
for (let callback of this.fulfillmentCallbacks) {
callback(this.result);
}
}
onRejected() {
for (let callback of this.rejectionCallbacks) {
callback(this.result);
}
}
5. then() 方法
then() 方法是 Promise 的核心,它允许我们指定在 Promise 状态改变后要执行的回调函数。
then(onFulfilled, onRejected) {
if (this.state === FULFILLED) {
onFulfilled(this.result);
} else if (this.state === REJECTED) {
onRejected(this.result);
} else {
this.fulfillmentCallbacks.push(onFulfilled);
this.rejectionCallbacks.push(onRejected);
}
return this;
}
6. catch() 方法
catch() 方法是 then() 方法的一个语法糖,它只处理 Promise 拒绝的情况。
catch(onRejected) {
return this.then(null, onRejected);
}
应用实例
现在我们有了自己的 Promise 实现,让我们用一个例子来展示它的用法。
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('成功啦!');
}, 2000);
});
promise
.then((result) => {
console.log(result); // 输出:成功啦!
})
.catch((error) => {
console.error(error);
});
结语
通过从头开始实现 Promise,我们不仅加深了对异步编程的理解,也领会了 Promise 的精妙之处。现在,我们可以在自己的代码中自信地使用 Promise,提升编程效率和代码可读性。欢迎留言分享你的见解和实践经验,让我们共同探索编程世界的无限可能!