特点
Promise 有以下两个特点:
1、对象的状态不受外界影响,Promise对象代表一个异步操作,共有三个状态
(1)pending:初始状态
(2)fulfilled:操作成功
(3)rejected:操作失败
2、一旦状态发生改变,就不会再发生变化。Promise 对象的状态改变,只有两种可能:从 Pending 变为 Resolved 和从 Pending 变为 Rejected。
代码实现
class myPromise{
static PENDING = 'pending';
static FULFILLED = 'fulfilled';
static REJECTED = 'rejected';
constructor(func){
this.PromiseState = myPromise.PENDING;
this.PromiseResult = null;
this.onFulfilledCallbacks = []; // 保存成功回调
this.onRejectedCallbacks = []; // 保存失败回调
try {
func(this.resolve.bind(this), this.reject.bind(this));
} catch (error) {
this.reject(error);
}
}
resolve(result){
// 修改状态为 fullfilled
if(this.PromiseState === myPromise.PENDING){
setTimeout(()=>{
this.PromiseState = myPromise.FULFILLED;
this.PromiseResult = result;
this.onFulfilledCallbacks.forEach(callback => {
callback(result)
})
});
}
}
reject(reason){
// 修改状态为 rejected
if(this.PromiseState === myPromise.PENDING){
setTimeout(()=>{
this.PromiseState = myPromise.REJECTED;
this.PromiseResult = reason;
this.onRejectedCallbacks.forEach(callback => {
callback(reason)
})
});
}
}
then(onFulfilled, onRejected){
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : () => {};
onRejected = typeof onRejected === 'function' ? onRejected : () => {};
// 处理链式调用
const promise = new myPromise((resolve, reject)=>{
if (this.PromiseState === myPromise.FULFILLED) {
/**
* 如果当前实例的 PromiseState 状态属性为 fulfilled 成功 的话,我们就执行传进来的 onFulfilled 函数
* 并且为onFulfilled函数传入前面保留的PromiseResult属性值
*/
setTimeout(() => {
onFulfilled(this.PromiseResult);
});
} else if (this.PromiseState === myPromise.REJECTED) {
/**
* 如果当前实例的 PromiseState 状态属性为 rejected 拒绝 的话,我们就执行传进来的 onRejected 函数
* 并且为onRejected函数传入前面保留的PromiseResult属性值
*/
setTimeout(() => {
onRejected(this.PromiseResult);
});
} else if (this.PromiseState === myPromise.PENDING) {
this.onFulfilledCallbacks.push((res)=>{
const result = onFulfilled(res);
// 将上一个 then 的返回值,传递给下一个 then
resolve(result);
});
this.onRejectedCallbacks.push((err)=>{
const error = onRejected(err);
reject(error);
});
}
});
// 返回一个promise
return promise;
}
}