JavaScript中手写promise ?
参考回答:
手写一个简单的 Promise 实现可以帮助理解其内部机制。一个 Promise 主要有三个状态:pending、resolved(fulfilled)和 rejected。我们需要模拟这些状态变化以及相应的 then() 和 catch() 方法。
详细讲解与拓展:
下面是一个简化版的 Promise 实现:
class MyPromise {
constructor(executor) {
// 初始化状态
this.state = 'pending'; // 'pending' | 'fulfilled' | 'rejected'
this.value = undefined; // 存储成功的值
this.reason = undefined; // 存储失败的原因
this.onFulfilledCallbacks = []; // 存储成功的回调
this.onRejectedCallbacks = []; // 存储失败的回调
// resolve 方法,用来改变状态为 fulfilled,并返回值
const resolve = (value) => {
if (this.state === 'pending') {
this.state = 'fulfilled';
this.value = value;
// 执行所有成功回调
this.onFulfilledCallbacks.forEach(fn => fn(value));
}
};
// reject 方法,用来改变状态为 rejected,并返回原因
const reject = (reason) => {
if (this.state === 'pending') {
this.state = 'rejected';
this.reason = reason;
// 执行所有失败回调
this.onRejectedCallbacks.forEach(fn => fn(reason));
}
};
// 执行传入的 executor 函数
try {
executor(resolve, reject);
} catch (error) {
reject(error); // 如果 executor 中有异常,调用 reject
}
}
// then 方法,返回一个新的 Promise
then(onFulfilled, onRejected) {
// 如果 onFulfilled 不是函数,默认返回传入的值
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
// 如果 onRejected 不是函数,默认抛出错误
onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason };
// 返回一个新的 Promise
return new MyPromise((resolve, reject) => {
// 处理 Promise 状态变化后的回调
if (this.state === 'fulfilled') {
// 如果 Promise 已经是 fulfilled 状态,立即调用 onFulfilled
setTimeout(() => {
try {
const result = onFulfilled(this.value);
resolve(result);
} catch (error) {
reject(error);
}
});
} else if (this.state === 'rejected') {
// 如果 Promise 已经是 rejected 状态,立即调用 onRejected
setTimeout(() => {
try {
const result = onRejected(this.reason);
resolve(result);
} catch (error) {
reject(error);
}
});
} else {
// 如果 Promise 还处于 pending 状态,保存回调,待状态变化时调用
this.onFulfilledCallbacks.push(() => {
setTimeout(() => {
try {
const result = onFulfilled(this.value);
resolve(result);
} catch (error) {
reject(error);
}
});
});
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
const result = onRejected(this.reason);
resolve(result);
} catch (error) {
reject(error);
}
});
});
}
});
}
// catch 方法,处理 Promise 的 reject 状态
catch(onRejected) {
return this.then(null, onRejected);
}
}
解释:
constructor(executor):构造函数接受一个executor函数,它有两个参数:resolve和reject。当异步操作成功时,调用resolve(value);失败时,调用reject(reason)。this.state:表示Promise的状态,可以是'pending'(待定),'fulfilled'(已解决),或者'rejected'(已拒绝)。this.value和this.reason:分别存储成功的结果和失败的原因。this.onFulfilledCallbacks和this.onRejectedCallbacks:分别用于存储then方法中的成功回调和失败回调。
then(onFulfilled, onRejected):then方法会返回一个新的Promise,这是Promise链式调用的关键。它接受两个回调函数,分别处理成功和失败的结果。如果当前Promise已经是fulfilled或rejected状态,立即调用相应的回调。如果是pending状态,则将回调存储起来,等待状态改变时执行。-
catch(onRejected):catch方法是then方法的一个简写,用于处理失败的情况,它实际上调用的是then(null, onRejected)。
使用示例:
const myPromise = new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve('Success');
}, 1000);
});
myPromise.then((value) => {
console.log(value); // 输出 'Success'
return 'Another success';
}).then((value) => {
console.log(value); // 输出 'Another success'
}).catch((error) => {
console.log(error);
});
详细讲解:
- 状态变化:一旦
Promise被解析为fulfilled或rejected,状态就无法再更改,因此在resolve和reject中,我们只允许在pending状态下修改状态。 - 回调队列:当
Promise仍处于pending状态时,then()会将回调函数加入队列。状态变化时,回调函数会被按顺序执行。 setTimeout:在then()和catch()中使用setTimeout来确保回调函数在事件循环的下一轮执行,以便模拟异步行为。
总结:
手写 Promise 是理解异步操作和 Promise 工作原理的一个好方法。通过实现基本的 resolve、reject、then()、catch() 方法,我们能够模拟异步操作并处理回调链。这个实现虽然简单,但已经涵盖了 Promise 的基本功能。在实际应用中,我们通常使用内建的 Promise,而手写实现有助于深入理解异步编程的核心概念。