带着手写 Promise,拨开异步编程的迷雾
2023-11-13 08:40:56
走进 Promise 的世界
Promise 的出现,为我们处理异步操作带来了新的可能。它提供了一个统一的 API,让我们可以轻松地处理异步任务的结果,并且可以对这些结果进行链式操作,从而使代码更加简洁和易于理解。
手把手构建 Promise
为了更好地理解 Promise 的工作原理,我们不妨亲手构建一个简易版的 Promise。首先,我们需要定义一个 Promise 构造函数,它接受一个执行器函数作为参数。这个执行器函数包含两个参数:resolve 和 reject,它们分别用于将 Promise 的状态从“等待”变为“成功”或“失败”。
function Promise(executor) {
this.state = "pending";
this.value = undefined;
this.reason = undefined;
this.onFulfilledCallbacks = [];
this.onRejectedCallbacks = [];
// 执行器函数
try {
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
在 Promise 构造函数中,我们定义了 Promise 的初始状态、值、原因,以及两个用于存储回调函数的数组。然后,我们使用 try...catch 语句来执行执行器函数。如果执行器函数执行成功,则调用 resolve 函数将 Promise 的状态从“等待”变为“成功”;如果执行器函数执行失败,则调用 reject 函数将 Promise 的状态从“等待”变为“失败”。
then 方法揭秘
Promise 的 then 方法用于处理 Promise 的结果。它接受两个参数:onFulfilled 和 onRejected,它们分别用于处理 Promise 的成功和失败状态。
Promise.prototype.then = function(onFulfilled, onRejected) {
// 如果 onFulfilled 不是函数,则使用默认函数
onFulfilled = typeof onFulfilled === "function" ? onFulfilled : function(value) {
return value;
};
// 如果 onRejected 不是函数,则使用默认函数
onRejected = typeof onRejected === "function" ? onRejected : function(reason) {
throw reason;
};
// 根据 Promise 的状态,将回调函数推入相应的数组
if (this.state === "fulfilled") {
setTimeout(() => {
onFulfilled(this.value);
}, 0);
} else if (this.state === "rejected") {
setTimeout(() => {
onRejected(this.reason);
}, 0);
} else {
this.onFulfilledCallbacks.push(onFulfilled);
this.onRejectedCallbacks.push(onRejected);
}
// 返回一个新的 Promise
return new Promise((resolve, reject) => {
// 在 onFulfilled 回调函数中,调用 resolve 函数
this.onFulfilledCallbacks.push((value) => {
try {
const result = onFulfilled(value);
resolve(result);
} catch (error) {
reject(error);
}
});
// 在 onRejected 回调函数中,调用 reject 函数
this.onRejectedCallbacks.push((reason) => {
try {
const result = onRejected(reason);
resolve(result);
} catch (error) {
reject(error);
}
});
});
};
在 then 方法中,我们首先检查 onFulfilled 和 onRejected 是否为函数,如果不是,则使用默认函数。然后,根据 Promise 的状态,将回调函数推入相应的数组。如果 Promise 的状态为“成功”,则将 onFulfilled 回调函数推入 onFulfilledCallbacks 数组;如果 Promise 的状态为“失败”,则将 onRejected 回调函数推入 onRejectedCallbacks 数组。如果 Promise 的状态为“等待”,则将 onFulfilled 和 onRejected 回调函数分别推入 onFulfilledCallbacks 和 onRejectedCallbacks 数组。
最后,我们返回一个新的 Promise,这个新的 Promise 的状态由 onFulfilled 和 onRejected 回调函数决定。如果 onFulfilled 回调函数执行成功,则将 Promise 的状态变为“成功”;如果 onRejected 回调函数执行成功,则将 Promise 的状态变为“失败”。
Promise 的应用场景
Promise 在实际开发中有着广泛的应用场景,比如:
- 异步数据请求: Promise 可以轻松地处理异步数据请求,例如使用 fetch 函数发起 HTTP 请求。
- 定时器: Promise 可以用于处理定时器,例如使用 setTimeout 函数来延迟执行某个操作。
- 事件监听: Promise 可以用于监听事件,例如使用 addEventListener 函数来监听 DOM 事件。
结语
Promise 作为异步编程的利器,为开发者带来了更加便捷和高效的开发体验。通过手写一个简易版的 Promise,我们可以对 Promise 的工作原理有了更深入的理解。希望本文能够帮助你更好地掌握 Promise,并将其应用到实际开发中。