返回
掌控异步编程的利器:手动实现Promise的魅力
前端
2023-11-27 03:53:03
Promise,全称Promises/A+,是JavaScript中用于处理异步编程的神奇工具。它可以将异步操作转为可控、可管理的单位,使开发人员能够以同步的方式编写异步代码。这不仅提高了代码的可读性,也极大地简化了异步编程的复杂性。
构建基础版Promise
Promise的实现原理并不复杂,让我们从头开始构建一个基础版的Promise。
class Promise {
constructor(executor) {
this.status = "pending"; // 初始状态为pending
this.value = null; // 存放最终结果
this.reason = null; // 存放错误信息
this.onFulfilledCallbacks = []; // 存放成功回调函数
this.onRejectedCallbacks = []; // 存放失败回调函数
// 立即执行executor,并传入resolve和reject两个函数
try {
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
resolve(value) {
if (this.status !== "pending") return;
this.status = "fulfilled";
this.value = value;
// 执行所有成功回调函数
this.onFulfilledCallbacks.forEach((callback) => {
callback(this.value);
});
}
reject(reason) {
if (this.status !== "pending") return;
this.status = "rejected";
this.reason = reason;
// 执行所有失败回调函数
this.onRejectedCallbacks.forEach((callback) => {
callback(this.reason);
});
}
then(onFulfilled, onRejected) {
// 如果onFulfilled不是函数,则返回当前的Promise
if (typeof onFulfilled !== "function") {
return this;
}
// 如果onRejected不是函数,则返回当前的Promise
if (typeof onRejected !== "function") {
return this;
}
// 创建新的Promise
const newPromise = new Promise((resolve, reject) => {
// 成功回调函数
const fulfilledCallback = (value) => {
try {
// 调用onFulfilled,并传入当前Promise的value
const result = onFulfilled(value);
// 根据result决定是resolve还是reject
if (result instanceof Promise) {
result.then(resolve, reject);
} else {
resolve(result);
}
} catch (error) {
// 如果onFulfilled抛出错误,则reject新的Promise
reject(error);
}
};
// 失败回调函数
const rejectedCallback = (reason) => {
try {
// 调用onRejected,并传入当前Promise的reason
const result = onRejected(reason);
// 根据result决定是resolve还是reject
if (result instanceof Promise) {
result.then(resolve, reject);
} else {
resolve(result);
}
} catch (error) {
// 如果onRejected抛出错误,则reject新的Promise
reject(error);
}
};
// 根据当前Promise的状态,执行对应的回调函数
if (this.status === "fulfilled") {
fulfilledCallback(this.value);
} else if (this.status === "rejected") {
rejectedCallback(this.reason);
} else {
// 如果当前Promise处于pending状态,则将回调函数暂存起来
this.onFulfilledCallbacks.push(fulfilledCallback);
this.onRejectedCallbacks.push(rejectedCallback);
}
});
// 返回新的Promise
return newPromise;
}
}
异步处理和发布订阅
Promise的强大之处在于它可以处理异步操作。我们可以利用发布订阅的方式将回调函数暂存起来,最后再执行。这可以极大地简化异步编程的复杂性。
// 创建一个Promise
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("成功!");
}, 1000);
});
// 订阅成功回调函数
promise.then((result) => {
console.log(result); // 输出:成功!
});
在上面的例子中,我们创建了一个Promise,并在1秒后resolve了一个值。然后,我们订阅了成功回调函数,并在Promise resolve后执行该回调函数,从而输出结果。
链式调用
Promise还支持链式调用,这使得我们能够以一种简洁、可读的方式编写异步代码。
// 创建一个Promise
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("成功!");
}, 1000);
});
// 链式调用then方法
promise
.then((result) => {
console.log(result); // 输出:成功!
return result + " world"; // 返回一个新的Promise
})
.then((result) => {
console.log(result); // 输出:成功! world
});
在上面的例子中,我们使用链式调用了then方法。在第一个then方法中,我们输出结果并返回一个新的Promise。在第二个then方法中,我们输出新的Promise的结果。这使得我们可以将多个异步操作串联起来,并以一种简洁的方式处理结果。
结语
Promise是JavaScript中用于处理异步编程的神奇工具。它可以将异步操作转为可控、可管理的单位,使开发人员能够以同步的方式编写异步代码。这不仅提高了代码的可读性,也极大地简化了异步编程的复杂性。通过本文,您已经掌握了Promise的基础实现、异步处理和链式调用的原理。现在,您已经准备好将Promise应用到您的项目中,并享受异步编程带来的便利和乐趣。