Promise
手写Promise过程
分析:Promise最重要的有三个状态pending(等待),fufilled(完成),rejected(失败)
接下来我们手一个SimplePromise函数,包括基本的功能:resolve、reject 和 then 方法。
正常我们的Promise使用是这样子的
new Promise(( resolve, reject ) =>{}).then().catch()
接下里我们就一步步手写一个简单的 Promise
第一步:创建基础结构
我们先写一个类,SimplePromise,搭建好基础的Prmise结构
接下来我们分别:定义结构 状态 然后绑定 执行 executor 函数(负责定义异步操作成功或失败的逻辑),把当前函数的resolve和reject作为参数传递给它 定义resolve函数和reject函数,处理成功和失败时候的值和状态
class SimplePromise {
constructor(executor) {
this.state = 'pending'; // 初始状态
this.value = undefined; // 成功时的值
this.reason = undefined; // 失败时的原因
// 执行传入的函数
executor(this.resolve.bind(this), this.reject.bind(this));
}
resolve(value) {
// 将状态设置为已完成
this.state = 'fulfilled';
this.value = value;
}
reject(reason) {
// 将状态设置为已失败
this.state = 'rejected';
this.reason = reason;
}
}
补充: 上面的constructor函数是类的方法,在new SimplePromise()时会自动调用,不需要额外手动调用
第二步:实现 then 方法
接下来给SimplePromise 添加 then 方法,用于处理成功和失败的回调 这里接着:传入onFulfilled onRejected ,判断状态 成功操作value 失败操作reason
// then方法
then(onFulfilled, onRejected){
if(this.status=='fulfilled'){
onFulfilled(this.value);
}else if(this.status=='rejected'){
onRejected(this.reason);
}
}
第三步:处理异步情况
我们需要处理异步操作的情况,这样 then 方法可以在状态改变后被正确调用,我们将成功和失败的回调存储在数组中,这里我们依然放入我们的构造函数之中
定义成功回调数组 失败回调数组 resolve 和 reject 的时候处理回调函数数组 then的时候推入函数onFulfilled和onRejected到onResolvedCallbacks和onRejectedCallbacks 数组中
constructor(executor) {
// ... 省略之前的内容
this.onResolvedCallbacks = []; // 存储成功的回调
this.onRejectedCallbacks = []; // 存储失败的回调
}
resolve(value) {
if (this.state === 'pending') {
this.state = 'fulfilled';
this.value = value;
this.onResolvedCallbacks.forEach(callback => callback(value));
}
}
reject(reason) {
if (this.state === 'pending') {
this.state = 'rejected';
this.reason = reason;
this.onRejectedCallbacks.forEach(callback => callback(reason));
}
}
then(onFulfilled, onRejected) {
if (this.state === 'fulfilled') {
onFulfilled(this.value);
} else if (this.state === 'rejected') {
onRejected(this.reason);
} else if (this.state === 'pending') {
this.onResolvedCallbacks.push(() => {
onFulfilled(this.value);
});
this.onRejectedCallbacks.push(() => {
onRejected(this.reason);
});
}
}
补充:
这里我们需要注意的就是:
使用箭头函数将 onRejected(this.value) 封装起来,可以确保这个回调在 Promise 状态变为“拒绝”时才执行,而不是在它被添加到回调数组时立即执行。
因为箭头函数本身并不会立即执行,它的执行时机取决于它如何被调用
在 Promise 的上下文中,箭头函数被定义后,只是被存储在一个数组中,并不会立即执行。
this.onResolvedCallbacks.forEach(callback => callback(value));
在这里作用其实就是 遍历 this.onResolvedCallbacks 数组中的所有回调函数,并对每一个函数调用,传递一个参数 value。
通常发生在 Promise 的状态变为“已解决”(fulfilled)时,用于执行所有注册的回调。
第四步:添加错误处理
接下来我们尝试在回调中捕获异常,避免我们有未处理的错误
利用try carch 捕获正常异常信息 然后调用resolve 或者 reject 方法
// then方法
then(onFulfilled, onRejected) {
//2 捕获正常异常信息
const handleFulfilled=()=>{
try{
const result = onFulfilled(this.value);
resolve(result);
}catch(error){
reject(error)
}
}
const handleRejected=()=>{
try{
const result = onRejected(this.reason);
resolve(reason);
}catch(error){
reject(error)
}
}
// 1
if (this.status == 'fulfilled') {
// onFulfilled(this.value);
handleFulfilled() //3
} else if (this.status == 'rejected') {
// onRejected(this.reason);
handleRejected() //3
} else if (this.status == 'pending') {
// this.onFulfilledCallbacks.push(() => {
// onFulfilled(this.value);
// });
// this.onRejectedCallbacs.push(() => {
// onRejected(this.value);
// });
this.onResolvedCallbacks.push(handleFulfilled);
this.onRejectedCallbacks.push(handleRejected);
}
}
最终完整版实现
class SimplePromise {
constructor(executor) {
this.state = 'pending';
this.value = undefined;
this.reason = undefined;
this.onResolvedCallbacks = [];
this.onRejectedCallbacks = [];
const resolve = (value) => {
if (this.state === 'pending') {
this.state = 'fulfilled';
this.value = value;
this.onResolvedCallbacks.forEach(callback => callback(value));
}
};
const reject = (reason) => {
if (this.state === 'pending') {
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 SimplePromise((resolve, reject) => {
const handleFulfilled = () => {
try {
const result = onFulfilled(this.value);
resolve(result);
} catch (error) {
reject(error);
}
};
const handleRejected = () => {
try {
const result = onRejected(this.reason);
resolve(result);
} catch (error) {
reject(error);
}
};
if (this.state === 'fulfilled') {
handleFulfilled();
} else if (this.state === 'rejected') {
handleRejected();
} else if (this.state === 'pending') {
this.onResolvedCallbacks.push(handleFulfilled);
this.onRejectedCallbacks.push(handleRejected);
}
});
}
}
// 使用示例
const promise = new SimplePromise((resolve, reject) => {
setTimeout(() => {
resolve("成功!");
}, 1000);
});
promise.then(result => {
console.log(result); // "成功!"
}).catch(error => {
console.error(error);
});