返回
从零开始 - 40行代码实现一个简单 Promise 函数
前端
2024-01-20 00:43:14
引言:异步编程的必要性
在当今快节奏的网络世界中,异步编程已成为一项不可或缺的技术。它允许我们在不阻塞主线程的情况下执行耗时的任务,从而提供流畅且响应迅速的用户体验。然而,理解和实现异步编程却可能让人望而生畏。
认识 Promise
Promise 是 JavaScript 中用于异步编程的强大工具。它本质上是一个表示未来值的占位符,该值可以在将来某个时刻变为可用。
从头开始构建一个 Promise 函数
为了加深理解,让我们从头开始编写一个简单的 Promise 函数。只需 40 行代码,我们就能掌握 Promise 的基本原理:
const Promise = function(executor) {
// 当前 Promise 的状态
this.state = 'pending';
// 保存最终的值或错误
this.value = undefined;
// 存储所有注册的回调函数
this.callbacks = [];
// 立即执行 executor 函数
executor(resolve, reject);
};
// 用于将 Promise 状态从 pending 更改为 fulfilled 的函数
const resolve = value => {
if (this.state !== 'pending') return;
this.state = 'fulfilled';
this.value = value;
executeCallbacks(this.callbacks);
};
// 用于将 Promise 状态从 pending 更改为 rejected 的函数
const reject = reason => {
if (this.state !== 'pending') return;
this.state = 'rejected';
this.value = reason;
executeCallbacks(this.callbacks);
};
// 依次执行所有已注册的回调函数
const executeCallbacks = callbacks => {
for (let callback of callbacks) {
callback(this.value, this.state);
}
};
// then() 方法:注册回调函数
Promise.prototype.then = function(onFulfilled, onRejected) {
const callback = {
onFulfilled,
onRejected
};
// 如果 Promise 尚未完成,则存储回调函数以供以后执行
if (this.state !== 'pending') {
setTimeout(() => executeCallbacks([callback]));
} else {
this.callbacks.push(callback);
}
// 返回一个新的 Promise,以实现链式调用
return new Promise((resolve, reject) => {
callback.onFulfilled = value => {
if (onFulfilled) {
try {
const result = onFulfilled(value);
if (result instanceof Promise) {
result.then(resolve, reject);
} else {
resolve(result);
}
} catch (err) {
reject(err);
}
} else {
resolve(value);
}
};
callback.onRejected = reason => {
if (onRejected) {
try {
const result = onRejected(reason);
if (result instanceof Promise) {
result.then(resolve, reject);
} else {
reject(result);
}
} catch (err) {
reject(err);
}
} else {
reject(reason);
}
};
});
};
// catch() 方法:处理拒绝状态的快捷方式
Promise.prototype.catch = function(onRejected) {
return this.then(null, onRejected);
};
如何使用我们的 Promise 函数
现在我们已经有了自己的 Promise 函数,让我们看看如何使用它:
const promise = new Promise((resolve, reject) => {
// 模拟耗时的异步操作
setTimeout(() => {
const success = true;
if (success) {
resolve('操作成功');
} else {
reject(new Error('操作失败'));
}
}, 2000);
});
promise
.then(result => {
console.log(result); // 输出:"操作成功"
})
.catch(error => {
console.log(error); // 输出:Error('操作失败')
});
结论
通过动手构建一个简单的 Promise 函数,我们加深了对异步编程的理解。Promise 为管理异步操作提供了强大的方式,让我们能够构建响应迅速且易于维护的应用程序。即使只有 40 行代码,我们也能掌握 Promise 的基本原理,为我们的编码工具箱增添一项宝贵的能力。