返回
细分思维,手写Promise不再难!
前端
2024-01-18 14:09:47
如今,面试越来越内卷,动不动就手写各种源码,其中最让程序员头疼的恐怕就是手写Promise了。很多人一听到这个要求就头大,毫无思路,不知道从哪里下手。
其实,只要我们把功能需求拆封一下,分步骤实现,手写Promise就没有那么难了。
理解Promise
Promise是一个用来处理异步操作的类。它可以让你在执行异步操作后,链式调用一个或多个回调函数。当异步操作完成时,它会把结果或错误信息传递给回调函数。
Promise的结构
Promise类有三个状态:
- Pending: 异步操作还未开始或正在进行中。
- Fulfilled: 异步操作已完成且成功。
- Rejected: 异步操作已完成且失败。
每个Promise对象都有一个内部状态和一个回调函数队列。当Promise的状态发生变化时,它会依次执行回调函数队列中的函数。
如何使用Promise
要使用Promise,你需要创建一个Promise对象,并传入一个执行器函数。执行器函数有两个参数:resolve和reject。resolve用于在异步操作成功时调用,reject用于在异步操作失败时调用。
例如,以下代码演示了如何创建一个Promise对象并使用它:
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
if (Math.random() < 0.5) {
resolve("成功!");
} else {
reject("失败!");
}
}, 1000);
});
promise.then((result) => {
console.log(result);
}, (error) => {
console.log(error);
});
手写Promise
现在,我们来看看如何手写一个Promise类。
首先,我们需要定义一个Promise类:
class Promise {
constructor(executor) {
this.state = "pending";
this.value = null;
this.error = null;
this.onFulfilledCallbacks = [];
this.onRejectedCallbacks = [];
try {
executor(this.resolve.bind(this), this.reject.bind(this));
} catch (error) {
this.reject(error);
}
}
resolve(value) {
if (this.state !== "pending") {
return;
}
this.state = "fulfilled";
this.value = value;
this.onFulfilledCallbacks.forEach((callback) => {
callback(this.value);
});
}
reject(error) {
if (this.state !== "pending") {
return;
}
this.state = "rejected";
this.error = error;
this.onRejectedCallbacks.forEach((callback) => {
callback(this.error);
});
}
then(onFulfilled, onRejected) {
if (typeof onFulfilled !== "function") {
onFulfilled = (value) => value;
}
if (typeof onRejected !== "function") {
onRejected = (error) => {
throw error;
};
}
const promise = new Promise((resolve, reject) => {
if (this.state === "fulfilled") {
setTimeout(() => {
try {
const result = onFulfilled(this.value);
resolve(result);
} catch (error) {
reject(error);
}
}, 0);
} else if (this.state === "rejected") {
setTimeout(() => {
try {
const result = onRejected(this.error);
resolve(result);
} catch (error) {
reject(error);
}
}, 0);
} else {
this.onFulfilledCallbacks.push((value) => {
setTimeout(() => {
try {
const result = onFulfilled(value);
resolve(result);
} catch (error) {
reject(error);
}
}, 0);
});
this.onRejectedCallbacks.push((error) => {
setTimeout(() => {
try {
const result = onRejected(error);
resolve(result);
} catch (error) {
reject(error);
}
}, 0);
});
}
});
return promise;
}
}
然后,我们就可以像之前一样使用这个Promise类了:
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
if (Math.random() < 0.5) {
resolve("成功!");
} else {
reject("失败!");
}
}, 1000);
});
promise.then((result) => {
console.log(result);
}, (error) => {
console.log(error);
});
总结
通过拆解需求,我们可以将手写Promise的过程分解为更小的步骤,从而使它变得更加容易理解和实现。希望本文能够帮助你掌握手写Promise的技巧,以便在面试中表现出色。