本文深入解析JavaScript中Promise的手写实现,涵盖从基础构造函数到then、catch链式调用的完整逻辑。通过剖析状态机流转、微任务调度及错误捕获机制,帮助开发者透彻理解Promise内部原理,从容应对技术面试中的源码级考察。
Promise手写
在JavaScript技术面试中,Promise相关题目属于高频考点,其中要求候选人手写实现Promise更是面试官的常规提问。因此,深入理解并掌握Promise的内部机制与实现细节至关重要。
框架
(function(window) {
MyPromise.prototype.then = function (onResolved, onRejected) {}
MyPromise.prototype.catch = function (onRejected) {}
function MyPromise(executor){
function resolve(value){}
function reject(error){}
try{
executor(resolve, reject)
}catch(error){
reject(error)
}
}
window.MyPromise = MyPromise
}(window))完整代码
(function (window) {
//将.then,.catch方法挂载在MyPromise原型上
MyPromise.prototype.then = function (onResolved, onRejected) {//.then接受两个回调函数,resolved状态和rejeced状态
// .then返回一个promise对象
return new MyPromise((resolve, reject) => {
let self = this;
if (self.status === 'pending') {//如果MyPromise状态为pending,将两个回调函数push进回调数组中等待
this.callbacks.push({ onResolved, onRejected })
} else if (self.status === 'resolved') { //如果MyPromise状态为resolved,将onResolved直接调用
setTimeout(() => {
//检查.then中的回调有没有return返回值
const result = onResolved(self.data)
//如果没有return返回值,默认返回promise对象
if (result instanceof MyPromise) {
result.then((res => resolve(res), err => reject(err)))
return result
} else {
resolve(result)
}
})
} else {
setTimeout(() => {
onResolved(self.data)
})
}
})
}
MyPromise.prototype.catch = function (onRejected) { //.catch接受一个回调函数
if (this.status === 'pending') {
// 将回调函数放入callbacks数组中
this.callbacks.push({ onRejected })
} else if (this.status === 'rejected') {
setTimeout(() => {
onRejected(this.data)
})
}
}
// MyPromise构造函数接受一个执行函数
function MyPromise(executor) {
const self = this;
self.data = undefined;
self.callbacks = []
//设置promise对象初始状态为pending
self.status = 'pending'
//执行函数第一个参数为resolve回调
function resolve(value) {
//如果状态不是pending,则直接返回
if (self.status !== 'pending') {
return
}
// 执行resolve,promise对象状态变更
self.status = 'resolved';
// 拿到resolve中的值
self.data = value;
// 调用callbacks中的回调函数
if (self.callbacks.length > 0) {
setTimeout(() => {
self.callbacks.forEach(callbacksObj => {
callbacksObj.onResolved(value)
});
})
}
}
// 执行函数第二个参数为rejecr回调
function reject(error) {
//如果状态不是pending,则直接返回
if (self.status !== 'pending') {
return
}
// 执行resolve,promise对象状态变更
self.status = 'rejected';
// 拿到resolve中的值
self.data = error;
// 调用callbacks中的回调函数
if (self.callbacks.length > 0) {
setTimeout(() => {
self.callbacks.forEach(callbacksObj => {
callbacksObj.onRejected(value)
});
})
}
}
//使用try catch捕获错误
try {
// 在try内执行执行函数
executor(resolve, reject)
} catch (error) {
// 如果出错,默认执行reject
reject(error);
}
}
window.MyPromise = MyPromise
}(window))测试
resolve
let MyPromiseTest = new MyPromise((resolve, reject) => {
resolve('resolve')
})
MyPromiseTest.then(res => {
console.log(res);
})
// resolve let MyPromiseTest = new MyPromise((resolve, reject) => {
resolve('resolve');
})
MyPromiseTest.then(res => {
console.log(res);
})
.then(res => {
console.log('我是.then()后面的.then()');
})
// resolve
// 我是.then()后面的.then()
reject
let MyPromiseTest = new MyPromise((resolve, reject) => {
reject('reject')
})
MyPromiseTest.catch(err => {
console.log(err);
})
// reject
let MyPromiseTest = new MyPromise((resolve, reject) => {
console.log(a);
})
MyPromiseTest.catch(err => {
console.log('捕获错误' + ':' + err);
})
// 捕获错误:ReferenceError: a is not defined至此,关于JavaScript面试中Promise手写实现的介绍已告一段落。如需了解更多相关技术内容,建议查阅本站往期文章或继续浏览后续章节,感谢大家的支持。