返回
深入浅出自制 Promise
前端
2023-12-06 14:56:17
纵观 JavaScript 的发展史,Promise 的出现可谓是一次划时代的革新,它优雅地解决了异步编程中回调地狱的问题。虽然 ES6 仅提供了 Promise A+ 规范,但实际实现却交由各浏览器厂商负责。本文将带领你踏上自制 Promise 的探索之旅,让你亲手领略 Promise 的精妙之处。
为何自制 Promise?
自制 Promise 并非为了替代原生 Promise,而是为了加深对 Promise 原理的理解。通过亲自动手实现,我们可以从底层洞悉 Promise 的工作机制,为后续深入学习和疑难解答奠定坚实的基础。
Promise A+ 规范
在着手自制 Promise 之前,我们必须牢牢把握 Promise A+ 规范。该规范定义了 Promise 的行为准则,包括:
- 状态变更:Promise 只能从 "pending" 变为 "fulfilled" 或 "rejected"。
- then 方法:then 方法允许我们对 Promise 的结果进行处理。
- catch 方法:catch 方法用于处理 Promise 失败的情况。
自制 Promise 实现
下面,我们将逐一实现 Promise A+ 规范中的关键要素:
class Promise {
constructor(executor) {
this.state = "pending";
this.value = undefined;
this.reason = undefined;
this.onFulfilledCallbacks = [];
this.onRejectedCallbacks = [];
const resolve = (value) => {
if (this.state !== "pending") return;
this.state = "fulfilled";
this.value = value;
this.onFulfilledCallbacks.forEach(callback => callback(value));
};
const reject = (reason) => {
if (this.state !== "pending") return;
this.state = "rejected";
this.reason = reason;
this.onRejectedCallbacks.forEach(callback => callback(reason));
};
try {
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
then(onFulfilled, onRejected) {
return new Promise((resolve, reject) => {
if (this.state === "fulfilled") {
const result = onFulfilled(this.value);
result instanceof Promise ? result.then(resolve, reject) : resolve(result);
} else if (this.state === "rejected") {
onRejected(this.reason);
} else {
this.onFulfilledCallbacks.push(() => {
const result = onFulfilled(this.value);
result instanceof Promise ? result.then(resolve, reject) : resolve(result);
});
this.onRejectedCallbacks.push((reason) => onRejected(reason));
}
});
}
catch(onRejected) {
return this.then(null, onRejected);
}
}
实践应用
现在,让我们用自制 Promise 编写一个简单的 HTTP 请求函数:
function get(url) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open("GET", url);
xhr.onload = () => {
if (xhr.status === 200) {
resolve(xhr.responseText);
} else {
reject(new Error(`请求失败:${xhr.status}`));
}
};
xhr.onerror = () => reject(new Error("网络错误"));
xhr.send();
});
}
总结
自制 Promise 是一段既有挑战性又有收获的旅程。通过亲自动手实现 Promise A+ 规范,我们不仅加深了对 Promise 原理的理解,还培养了独立解决问题的能力。这种经验对于我们成为一名合格的前端开发者至关重要。