从零构建 Promise:分步指南
2023-09-06 10:56:44
引言
Promise 作为一种成熟的异步编程解决方案,以其简洁易用、强大的错误处理机制和可组合性而著称。虽然理解和使用 Promise 并不难,但要真正掌握它们,还需要更深入地了解其底层工作原理。通过亲自动手实现 Promise,你可以获得宝贵的见解,并提升对异步编程概念的掌握程度。
第 1 步:初始化
首先,我们需要一个构造函数来创建 Promise 实例。Promise 构造函数接受一个 executor 函数作为参数,该函数接收 resolve 和 reject 两个回调函数,用于在 Promise 完成或拒绝时调用。
function Promise(executor) {
this.state = 'pending';
this.value = undefined;
this.error = undefined;
this.onResolveCallbacks = [];
this.onRejectCallbacks = [];
// 执行 executor 函数,传入 resolve 和 reject 回调函数
executor(resolve, reject);
}
第 2 步:解析和拒绝
resolve 和 reject 函数用于改变 Promise 的状态。resolve 将 Promise 的状态设置为 "fulfilled" 并设置一个值,而 reject 将状态设置为 "rejected" 并设置一个错误。
Promise.prototype.resolve = function(value) {
if (this.state !== 'pending') return;
this.state = 'fulfilled';
this.value = value;
// 调用所有 onResolveCallbacks
for (let callback of this.onResolveCallbacks) {
callback(value);
}
};
Promise.prototype.reject = function(error) {
if (this.state !== 'pending') return;
this.state = 'rejected';
this.error = error;
// 调用所有 onRejectCallbacks
for (let callback of this.onRejectCallbacks) {
callback(error);
}
};
第 3 步:then() 方法
then() 方法是 Promise 的核心,它允许你为成功或失败的情况指定回调函数。
Promise.prototype.then = function(onResolve, onReject) {
// 如果 onResolve 或 onReject 未提供,则使用默认的回调函数
if (typeof onResolve !== 'function') {
onResolve = value => value;
}
if (typeof onReject !== 'function') {
onReject = error => { throw error; };
}
// 创建一个新的 Promise 来包装回调函数的结果
const newPromise = new Promise(() => {});
// 如果 Promise 已完成,则立即执行回调函数
if (this.state === 'fulfilled') {
setTimeout(() => {
try {
const result = onResolve(this.value);
newPromise.resolve(result);
} catch (error) {
newPromise.reject(error);
}
}, 0);
} else if (this.state === 'rejected') {
setTimeout(() => {
try {
const result = onReject(this.error);
newPromise.resolve(result);
} catch (error) {
newPromise.reject(error);
}
}, 0);
} else {
// 如果 Promise 仍处于待定状态,则将回调函数添加到 onResolveCallbacks 或 onRejectCallbacks 数组中
this.onResolveCallbacks.push(() => {
setTimeout(() => {
try {
const result = onResolve(this.value);
newPromise.resolve(result);
} catch (error) {
newPromise.reject(error);
}
}, 0);
});
this.onRejectCallbacks.push(() => {
setTimeout(() => {
try {
const result = onReject(this.error);
newPromise.resolve(result);
} catch (error) {
newPromise.reject(error);
}
}, 0);
});
}
// 返回新的 Promise
return newPromise;
};
第 4 步:使用 Promise
现在我们已经实现了 Promise,就可以开始使用它来编写异步代码了。以下是一个示例,说明如何使用 Promise 获取数据的异步函数:
const getData = () => {
return new Promise((resolve, reject) => {
// 模拟异步操作
setTimeout(() => {
if (Math.random() < 0.5) {
resolve('数据获取成功');
} else {
reject('数据获取失败');
}
}, 1000);
});
};
getData()
.then(result => {
console.log(result);
})
.catch(error => {
console.log(error);
});
结语
通过从零构建 Promise,你已经深入了解了 Promise 的内部工作原理和使用方式。这不仅增强了你的 JavaScript 技能,还为你提供了编写健壮、可维护的异步代码的宝贵见解。
掌握 Promise 将为你打开异步编程的大门,让你能够轻松处理并发操作、提高代码的可读性和提高应用程序的性能。继续探索 Promise 的高级特性,例如 Promise.all()、Promise.race() 和 async/await,以进一步提升你的异步编程能力。