返回
从零实现一个 Promise 的内在逻辑和实战应用
前端
2023-11-18 16:37:35
从头开始实现 Promise
为了更深入地理解 Promise 的运行机制,让我们从零开始实现一个简易版的 Promise。首先,我们先来定义一个 Promise 类:
class Promise {
constructor(executor) {
this.status = "pending"; // Promise 的初始状态是 pending
this.value = undefined; // Promise 的值,在 resolve 时确定
this.reason = undefined; // Promise 的原因,在 reject 时确定
this.onResolveCallbacks = []; // 保存 then 回调函数,在 resolve 时执行
this.onRejectCallbacks = []; // 保存 then 回调函数,在 reject 时执行
// 立即执行 executor 函数
try {
executor(this.resolve.bind(this), this.reject.bind(this));
} catch (error) {
// 如果 executor 函数抛出错误,则以 reject 状态扭转 Promise
this.reject(error);
}
}
resolve(value) {
if (this.status === "pending") {
this.status = "fulfilled"; // 将 Promise 状态变更为 fulfilled
this.value = value; // 将 Promise 的值设置为给定值
this.onResolveCallbacks.forEach(callback => callback(value)); // 执行所有 then 回调函数
}
}
reject(reason) {
if (this.status === "pending") {
this.status = "rejected"; // 将 Promise 状态变更为 rejected
this.reason = reason; // 将 Promise 的原因设置为给定原因
this.onRejectCallbacks.forEach(callback => callback(reason)); // 执行所有 then 回调函数
}
}
then(onResolve, onReject) {
// 如果 onResolve 或 onReject 为空,则直接返回一个新的 Promise
if (typeof onResolve !== "function") {
onResolve = value => value;
}
if (typeof onReject !== "function") {
onReject = reason => { throw reason; };
}
// 返回一个新的 Promise 对象
return new Promise((resolve, reject) => {
// 将 then 回调函数添加到回调数组中
this.onResolveCallbacks.push(value => {
try {
// 执行 then 回调函数,并把结果作为新的 Promise 的值
const result = onResolve(value);
resolve(result); // 以 resolve 状态扭转新的 Promise
} catch (error) {
// 如果 then 回调函数抛出错误,则以 reject 状态扭转新的 Promise
reject(error);
}
});
this.onRejectCallbacks.push(reason => {
try {
// 执行 then 回调函数,并把结果作为新的 Promise 的值
const result = onReject(reason);
resolve(result); // 以 resolve 状态扭转新的 Promise
} catch (error) {
// 如果 then 回调函数抛出错误,则以 reject 状态扭转新的 Promise
reject(error);
}
});
});
}
}
实战应用:Promise 的妙用
为了更好地理解 Promise 的实际应用,让我们来看一个简单的示例。假设我们有一个异步函数 fetchUser
,它从服务器获取用户信息。我们希望在获取用户信息后,再执行一些操作,例如更新 UI。
// 获取用户信息的异步函数
const fetchUser = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
// 模拟从服务器获取用户信息
const user = { name: "John Doe", age: 30 };
resolve(user); // 以 resolve 状态扭转 Promise,并传入用户信息
}, 1000);
});
};
// 使用 Promise 链式调用来更新 UI
fetchUser()
.then(user => {
// 更新 UI,显示用户信息
document.getElementById("user-name").innerHTML = user.name;
document.getElementById("user-age").innerHTML = user.age;
})
.catch(error => {
// 处理错误情况
console.error(error);
});
在这个示例中,我们首先调用 fetchUser
函数获取用户信息,并返回一个 Promise。然后,我们使用 then
方法来注册一个回调函数,当 Promise 状态变更为 resolved 时,该回调函数将被执行,并在回调函数中更新 UI。如果 Promise 状态变更为 rejected,则会执行 catch
方法中的回调函数,并在该回调函数中处理错误情况。
结语
Promise 作为 JavaScript 中一项强大的异步编程工具,它可以帮助我们更优雅地处理异步任务,并编写出更易读、更易维护的代码。通过本文的深入剖析,您应该已经对 Promise 的工作原理有了更清晰的认识。