返回
深层探究:手写符合 Promise/A+ 规范的 Promise 源码,解析异步编程精髓
前端
2023-11-01 12:21:06
Promise 是 JavaScript 中异步编程的核心,也是前端面试的高频问题。要成为一名优秀的前端工程师,掌握 Promise 及其底层实现原理至关重要。
本文将从 Promise/A+ 规范解读入手,带你深入理解 Promise 的工作原理。随后,我们将手写一个符合 Promise/A+ 规范的 Promise 源码,让你对 Promise 的内部机制有更深刻的认识。
Promise/A+ 规范解读
Promise/A+ 规范定义了 Promise 对象的行为和交互方式,确保不同实现的 Promise 对象具有统一的语义。该规范包含以下几个关键概念:
- Promise 对象: 表示一个异步操作的最终完成或失败及其结果值。
- Promise 状态: Promise 对象有三种状态:Pending(等待)、Fulfilled(已完成)和 Rejected(已失败)。
- Promise 回调函数: then() 方法用于注册回调函数,当 Promise 对象状态改变时,这些回调函数会被调用。
- Promise 链式调用: then() 方法可以返回一个新的 Promise 对象,从而形成 Promise 链。
手写 Promise 源码
为了更深入地理解 Promise 的工作原理,我们现在将手写一个符合 Promise/A+ 规范的 Promise 源码。
class Promise {
constructor(executor) {
this.state = "pending";
this.value = undefined;
this.reason = undefined;
this.onFulfilledCallbacks = [];
this.onRejectedCallbacks = [];
// 执行器函数的调用,并传入 resolve 和 reject 两个函数
try {
executor(this.resolve.bind(this), this.reject.bind(this));
} catch (err) {
this.reject(err);
}
}
resolve(value) {
// 只能从 pending 状态变为 fulfilled 状态
if (this.state !== "pending") {
return;
}
this.state = "fulfilled";
this.value = value;
// 依次执行成功的回调函数
this.onFulfilledCallbacks.forEach((callback) => {
callback(this.value);
});
}
reject(reason) {
// 只能从 pending 状态变为 rejected 状态
if (this.state !== "pending") {
return;
}
this.state = "rejected";
this.reason = reason;
// 依次执行失败的回调函数
this.onRejectedCallbacks.forEach((callback) => {
callback(this.reason);
});
}
then(onFulfilled, onRejected) {
// 返回一个新的 Promise 对象
return new Promise((resolve, reject) => {
// 处理同步情况
if (this.state === "fulfilled") {
setTimeout(() => {
try {
// 执行成功的回调函数
const value = onFulfilled(this.value);
resolve(value);
} catch (err) {
reject(err);
}
}, 0);
} else if (this.state === "rejected") {
setTimeout(() => {
try {
// 执行失败的回调函数
const reason = onRejected(this.reason);
resolve(reason);
} catch (err) {
reject(err);
}
}, 0);
} else {
// 处理异步情况
// 将成功的回调函数存储起来
this.onFulfilledCallbacks.push(() => {
setTimeout(() => {
try {
// 执行成功的回调函数
const value = onFulfilled(this.value);
resolve(value);
} catch (err) {
reject(err);
}
}, 0);
});
// 将失败的回调函数存储起来
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
// 执行失败的回调函数
const reason = onRejected(this.reason);
resolve(reason);
} catch (err) {
reject(err);
}
}, 0);
});
}
});
}
// 辅助方法,用于 Promise 链式调用的终止
catch(onRejected) {
return this.then(undefined, onRejected);
}
// 辅助方法,用于 Promise 的并行处理
static all(promises) {
return new Promise((resolve, reject) => {
// 结果数组,用于存储每个 Promise 的结果
const results = [];
// 记录已完成的 Promise 的数量
let completedCount = 0;
// 遍历每个 Promise
promises.forEach((promise, index) => {
// 将 Promise 的结果存储在结果数组中
promise
.then((value) => {
results[index] = value;
completedCount++;
// 当所有 Promise 都已完成时,resolve 最终的 Promise
if (completedCount === promises.length) {
resolve(results);
}
})
.catch((reason) => {
// 只要有一个 Promise 失败,就 reject 最终的 Promise
reject(reason);
});
});
});
}
// 辅助方法,用于 Promise 的串行处理
static race(promises) {
return new Promise((resolve, reject) => {
// 遍历每个 Promise
promises.forEach((promise) => {
// 只要有一个 Promise 完成或失败,就 resolve 或 reject 最终的 Promise
promise
.then((value) => {
resolve(value);
})
.catch((reason) => {
reject(reason);
});
});
});
}
}
使用手写的 Promise
const promise = new Promise((resolve, reject) => {
// 模拟异步操作
setTimeout(() => {
resolve("Hello, Promise!");
}, 1000);
});
promise
.then((value) => {
console.log(value); // 输出: "Hello, Promise!"
})
.catch((reason) => {
console.log(reason); // 不会被调用
});
结语
通过手写 Promise 源码,我们对 Promise 的工作原理有了更深入的理解。Promise 是 JavaScript 中异步编程的核心,掌握其原理和用法对前端工程师来说至关重要。希望本文能帮助读者更好地理解 Promise,并在实际项目中熟练使用它。