准备工作
1.Promise首先要接收一个函数当作参数,函数里又分别带有两个参数,分别是resolve
回调和reject
回调
2.Promise的状态有三种:等待(pending
)、已完成(fulfilled
)、已拒绝(rejected
),并且状态只能由等待到完成
或者等待到拒接
。
3.初始化状态 等待(pending
)
const PHB_PENDING = 'pending';
const PHB_FULFILLED = 'fulfilled';
const PHB_REJECTED = 'rejected';
class PHBPromise {
constructor(executor) {
// 初始化状态 pending(未决定)
this.state = PHB_PENDING;
// 成功回调
let resolve = () => {
console.log('成功');
};
// 失败回调
let reject = () => {
console.log('失败');
};
// 执行接收的函数并传入函数参数,executor也会可能存在异常,因此通过try/catch来捕获一下异常情况
try {
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
let phbPromise = new PHBPromise((resolve, reject) => {
resolve('成功');
});
then方法
1.先简单搭建骨架
new phbPromise可以调用多个.then
所以成功回调、失败回调都使用数组存放
this.onFulfilled
= []; //成功 this.onRejected
= []; //失败
then(onfulfilled, onrejected) {
this.onFulfilled.push(onfulfilled);
this.onRejected.push(onrejected);
}
状态只能由等待到完成或者等待到拒接
进入rosolve
修改状态为已完成(fulfilled),进入reject
,修改状态为已拒绝(rejected)
这个时候我们执行下代码看下有什么问题
// “Promise的三种状态: pending、fulfilled、rejected(等待,已完成,已拒绝)
const PHB_PENDING = 'pending';
const PHB_FULFILLED = 'fulfilled';
const PHB_REJECTED = 'rejected';
class PHBPromise {
constructor(executor) {
this.state = PHB_PENDING; // 初始化状态 pending(等待)
this.value = null; //成功的结果或者失败的结果
this.onFulfilled = []; //成功的回调
this.onRejected = []; //失败的回调
// 成功回调
let resolve = value => {
if (this.state === PHB_PENDING) {
this.value = value;
this.state = PHB_FULFILLED; //修改状态为已完成(fulfilled)
this.onFulfilled.forEach(item => {
item(this.value);
});
}
};
// 失败回调
let reject = reason => {
if (this.state === PHB_PENDING) {
this.value = reason;
this.state = PHB_REJECTED; //修改状态为已拒绝(rejected)
this.onRejected.forEach(item => {
item(this.value);
});
}
};
// 执行接收的函数并传入函数参数
executor(resolve, reject);
}
then(onfulfilled, onrejected) {
this.onFulfilled.push(onfulfilled);
this.onRejected.push(onrejected);
}
}
let phbPromise = new PHBPromise((resolve, reject) => {
resolve('成功');
});
// 调用.then方法
phbPromise.then(
res => {
console.log(res);
},
err => {
console.log(err);
}
);
这个时候我们可以发现控制台没有输出。
为什么没有输出?不是已经调用了resolve
?
答:在执行resolve时, phbPromise.then还未调用,还未把函数添加到this.onFulfilled
,所以这个时候this.onFulfilled还是一个空数组。
then方法bug解决方案
在执行resolve
先把它添加到微任务中,这个时候并不会阻塞,会继续执行后面代码 phbPromise.then
,等同步任务都执行完成后再去微任务中执行resolve代码,,这个时候this.onFulfilled就有值了
如果还不太了解同步或异步任务,可以去看下事件循环机制(Event Loop)
let phbPromise = new PHBPromise((resolve, reject) => {
resolve('成功');//添加微任务 代码继续向下执行
});
// 调用.then方法
phbPromise.then(
res => {
console.log(res);
},
err => {
console.log(err);
}
);
// 成功回调
let resolve = value => {
if (this.state === PHB_PENDING) {
// 添加到微任务
queueMicrotask(() => {
if (this.state === PHB_REJECTED) return;
this.value = value;
this.state = PHB_FULFILLED; //修改状态为已完成(fulfilled)
this.onFulfilled.forEach(item => {
item(this.value);
});
}, 0);
}
};
// 失败回调
let reject = reason => {
if (this.state === PHB_PENDING) {
// 添加到微任务
queueMicrotask(() => {
if (this.state === PHB_FULFILLED) return;
this.value = reason;
this.state = PHB_REJECTED; //修改状态为已拒绝(rejected)
this.onRejected.forEach(item => {
item(this.value);
});
}, 0);
}
};
这个时候我们抛出一个问题,模拟请求2秒后再去去调用phbPromise.then
,这个时候还会触发回调吗?
答:不会,这个时候微任务里面的resolve
早已经回调了。
let phbPromise = new PHBPromise((resolve, reject) => {
resolve('成功');
});
// 调用.then方法
phbPromise.then(
res => {
console.log(res);
},
err => {
console.log(err);
}
);
//调用.then还能触发resolve吗?
setTimeout(function () {
phbPromise.then(
res => {
console.log(res);
},
err => {
console.log(err);
}
);
}, 2000);
then方法bug解决方案
根据状态this.state
判断,如果this.state
已经是fulfilled
或者rejected
状态了,说明已经执行过resolve
,这个时候我们可以对传入的函数直接调用。
then(onfulfilled, onrejected) {
if (this.state === PHB_FULFILLED) {
onfulfilled(this.value);
}
if (this.state === PHB_REJECTED) {
onrejected(this.value);
}
if (this.state === PHB_PENDING) {
this.onFulfilled.push(onfulfilled);
this.onRejected.push(onrejected);
}
}
新需求,增加链式调用then
,也就是说,每个then
方法都要返回一个新的Promise
对象,这样我们的then
方法才能不断的链式调用
phbPromise
.then(
res => {
console.log(res);
return '第一个then得到成功的结果';
},
err => {
console.log(err);
return '第一个then得到失败的结果';
}
)
.then(
res1 => {
console.log(res1);
},
err2 => {
console.log(err2);
}
);
then方法bug解决方案
1.想要链式调用then
就必须要 new
一个新的实例对象
2.考虑到所有出错的情况所以都使用try/catch 包裹
3.重点是pending状态下(等待)this.onFulfilled.push一个箭头函数
then(onfulfilled, onrejected) {
// new一个新的实例对象,方便链式调用
return new PHBPromise((resolve, reject) => {
// 状态为已完成(fulfilled)
if (this.state === PHB_FULFILLED) {
try {
this.value = onfulfilled(this.value);
resolve(this.value);
} catch (error) {
reject(this.value);
}
}
//状态为已拒绝(rejected)
if (this.state === PHB_REJECTED) {
try {
this.value = onrejected(this.value);
console.log(this.value);
resolve(this.value);
} catch (error) {
reject(this.value);
}
}
//初始化状态 pending(等待)
if (this.state === PHB_PENDING) {
this.onFulfilled.push(() => {
try {
this.value = onfulfilled(this.value);
resolve(this.value);
} catch (error) {
reject(this.value);
}
});
this.onRejected.push(() => {
try {
this.value = onrejected(this.value);
resolve(this.value);
} catch (error) {
reject(this.value);
}
});
}
});
}
phbPromise
.then(
res => {
console.log(res);
return 'then成功回调1';
},
err => {
console.log(err);
return 'then失败回调1';
}
)
.then(
res1 => {
console.log(res1);
return 'then成功回调2';
},
err1 => {
console.log(err1);
return 'then失败回调2';
}
)
.then(
res2 => {
console.log(res2);
},
err2 => {
console.log(err2);
}
);
抛出一个需求:让then
方法可以只传递onfulfilled
函数,可以通过catch
接收失败的回调
then方法bug解决方案
1.当调用then(onfulfilled)
,onrejected没有值的情况下,默认给个函数返回一个异常
2.onfulfilled
没有值的情况下,默认给个一个函数,返回传入的参数,为catch
做铺垫
// catch 只传入失败回调 onfulfille没有的话默认给个函数
onfulfilled = onfulfilled || (value => {return value; });
// then方法可以只传入成功回调 当onrejected没传的话默认给个函数抛出异常
onrejected = onrejected || (value => { throw this.value;});
最终完整版 then
then(onfulfilled, onrejected) {
// catch 只传入失败回调 onfulfille没有的话默认给个函数
onfulfilled = onfulfilled || (value => {return value; });
// then方法可以只传入成功回调 当onrejected没传的话默认给个函数抛出异常
onrejected = onrejected || (value => { throw this.value;});
// new一个新的实例对象,方便链式调用
return new PHBPromise((resolve, reject) => {
// 状态为已完成(fulfilled)
if (this.state === PHB_FULFILLED) {
try {
this.value = onfulfilled(this.value);
resolve(this.value);
} catch (error) {
reject(this.value);
}
}
//状态为已拒绝(rejected)
if (this.state === PHB_REJECTED) {
try {
this.value = onrejected(this.value);
resolve(this.value);
} catch (error) {
reject(this.value);
}
}
//初始化状态 pending(等待)
if (this.state === PHB_PENDING) {
this.onFulfilled.push(() => {
try {
this.value = onfulfilled(this.value);
resolve(this.value);
} catch (error) {
reject(this.value);
}
});
this.onRejected.push(() => {
try {
this.value = onrejected(this.value);
resolve(this.value);
} catch (error) {
reject(this.value);
}
});
}
});
}
catch
catch() 方法返回一个Promise (en-US),并且处理拒绝的情况。它的行为与调用Promise.prototype.then(undefined, onRejected)
相同。
只需要去调用then方法,传入onrejected
catch(onrejected) {
return this.then(undefined, onrejected);
}
}
let phbPromise = new PHBPromise((resolve, reject) => {
// resolve('成功');
reject('失败');
});
phbPromise
.then(res => {
console.log(res);
return 'then成功回调1';
})
.catch(err => {
console.log(err);
return '失败1';
})
.then(
res1 => {
console.log(res1);
},
err2 => {
console.lgo(err2);
}
);
finally
finally()
方法返回一个 Promise
。在 promise 结束时,无论结果是 fulfilled 或者是 rejected,都会执行指定的回调函数
finally(onFinally) {
this.then(onFinally, onFinally);
}
let phbPromise = new PHBPromise((resolve, reject) => {
// resolve('成功');
reject('失败');
});
phbPromise
.then(
res1 => {
console.log(res1);
},
err2 => {
console.log(err2);
}
)
.finally(function () {
console.log('finally执行了');
});
Promise.all(iterable)
1.接受一个[可迭代]对象,存储多个Promise
实例
2.返回一个新的 promise
对象,等到所有的 promise 对象都成功或失败,去执行resolve
或rejeck
3.一旦有任意一个 里面的 promise
对象失败则立即以该 promise
对象失败的理由来拒绝这个新的 promise
。
static all(iterable) {
return new PHBPromise((resolve, reject) => {
let value = [];//用于保存成功数据
iterable.forEach(item => {
item.then(
res => {
value.push(res); //成功就保存到数组
if (value.length === iterable.length) {
//全部执行完成就去调用resolve
resolve(value);
}
},
err => {
reject(err); //一个失败直接调用reject
}
);
});
});
}
}
let p1 = new PHBPromise((resolve, reject) => {
resolve('成功1');
});
let p2 = new PHBPromise((resolve, reject) => {
resolve('成功2');
});
let p3 = new PHBPromise((resolve, reject) => {
resolve('成功3');
});
PHBPromise.all([p1, p2, p3])
.then(res => {
console.log(res);
})
.catch(err => {
console.log(err);
});
Promise.allSettled(iterable)
1.返回一个在所有给定的 promise 都已经fulfilled
或rejected
后的 promise,并带有一个对象数组,每个对象表示对应的 promise 结果
2.通俗点来说就是不管成功还是失败都会把状态结果保存返回
static allSettled(iterable) {
return new PHBPromise(resolve => {
let value = [];
//allSettled只会执行成功回调
iterable.forEach(item => {
item.then(
res => {
value.push({
status: 'fulfilled', //保存状态,和结果
value: res,
});
if (value.length === iterable.length) {
resolve(value);
}
},
err => {
value.push({
status: 'rejected', //保存状态,和结果
value: err,
});
if (value.length === iterable.length) {
resolve(value);
}
}
);
});
});
}
let p1 = new PHBPromise((resolve, reject) => {
resolve('成功1');
});
let p2 = new PHBPromise((resolve, reject) => {
// resolve('成功2');
reject('失败');
});
let p3 = new PHBPromise((resolve, reject) => {
resolve('成功3');
});
PHBPromise.allSettled([p1, p2, p3]).then(res => {
console.log(res);
});
Promise.any(iterable)
1.单个拒绝状态不会调用rejeck,所以说new Peomise
只需要传递resolve
,如果所有状态都是拒绝,才会调用resolve抛出异常
2.只要有一个 promise
兑现了,那么此方法就会提前结束,而不会继续等待其他的 promise
全部敲定。
3.全部是拒绝状态,并且它的拒因会是一个 AggregateError
实例,这是 Error
的子类,用于把单一的错误集合在一起。
static any(iterable) {
let isResolve = false; //用于判断一个成功回调执行后其他不会执行
let index = 0;
return new PHBPromise(resolve => {
iterable.forEach(item => {
item.then(
res => {
if (isResolve) return; //如果为true 说明已经执行过resolve 后面的就不需要继续执行
resolve(res);
isResolve = true;
},
err => {
index++;
if (iterable.length === index) {
// AggregateError 把单一的错误集合在一起
resolve(new AggregateError('', 'No Promise in Promise.any was resolved'));
}
}
);
});
});
}
let p1 = new PHBPromise((resolve, reject) => {
// resolve('成功1');
reject('失败1');
});
let p2 = new PHBPromise((resolve, reject) => {
resolve('成功2');
// reject('失败1');
});
let p3 = new PHBPromise((resolve, reject) => {
reject('失败1');
// resolve('成功3');
});
PHBPromise.any([p1, p2, p3]).then(res => {
console.log(res);
});
Promise.race(iterable)
1.接收一个可迭代对象,类似Array
,
race
函数返回一个 Promise
2.一旦迭代器中的某个promise
解决或拒绝,返回的 promise就会直接resolve
或reject
static race(iterable) {
let isCallBack = false; //用于判断一个成功回调执行后其他不会执行
return new PHBPromise((resolve, reject) => {
iterable.forEach(item => {
item.then(
res => {
if (isCallBack) return; // 为true 直接返回
resolve(res);
isCallBack = true;
},
err => {
if (isCallBack) return; // 为true 直接返回
reject(err);
isCallBack = true;
}
);
});
});
}
let p1 = new PHBPromise((resolve, reject) => {
setTimeout(() => {
reject('失败1');
}, 4000);
});
let p2 = new PHBPromise((resolve, reject) => {
setTimeout(() => {
resolve('成功2');
}, 2000);
});
let p3 = new PHBPromise((resolve, reject) => {
setTimeout(function () {
reject('失败2');
}, 3000);
});
PHBPromise.race([p1, p2, p3]).then(
res => {
console.log(res);
},
err => {
console.log(err);
}
);
Promise.resolve(value)
static resolve(value) {
return new PHBPromise(resolve => {
resolve(value);
});
}
PHBPromise.resolve('成功1')
.then(res => {
console.log(res);
return '成功2';
})
.then(res => {
console.log(res);
});
Promise.reject(reason)
static reject(value) {
return new PHBPromise((undefined, reject) => {
reject(value);
});
}
PHBPromise.reject('失败1')
.then(res => {
console.log(res);
})
.catch(err => {
console.log(err);
});
PHBPromise最终代码
// “Promise的三种状态: pending、fulfilled、rejected(等待,已完成,已拒绝)
const PHB_PENDING = 'pending';
const PHB_FULFILLED = 'fulfilled';
const PHB_REJECTED = 'rejected';
class PHBPromise {
constructor(executor) {
this.state = PHB_PENDING; // 初始化状态 pending(等待)
this.value = null; //成功的结果或者失败的结果
this.onFulfilled = []; //成功的回调
this.onRejected = []; //失败的回调
// 成功回调
let resolve = value => {
if (this.state === PHB_PENDING) {
// 添加到微任务
queueMicrotask(() => {
if (this.state === PHB_REJECTED) return;
this.value = value;
this.state = PHB_FULFILLED; //修改状态为已完成(fulfilled)
this.onFulfilled.forEach(item => {
item(this.value);
});
}, 0);
}
};
// 失败回调
let reject = reason => {
if (this.state === PHB_PENDING) {
// 添加到微任务
queueMicrotask(() => {
if (this.state === PHB_FULFILLED) return;
this.value = reason;
this.state = PHB_REJECTED; //修改状态为已拒绝(rejected)
this.onRejected.forEach(item => {
item(this.value);
});
}, 0);
}
};
// 执行接收的函数并传入函数参数,executor也会可能存在异常,因此通过try/catch来捕获一下异常情况
try {
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
then(onfulfilled, onrejected) {
// catch 只传入失败回调 onfulfille没有的话默认给个函数
onfulfilled = onfulfilled || (value => {return value; });
// then方法可以只传入成功回调 当onrejected没传的话默认给个函数抛出异常
onrejected = onrejected || (value => { throw this.value;});
// new一个新的实例对象,方便链式调用
return new PHBPromise((resolve, reject) => {
// 状态为已完成(fulfilled)
if (this.state === PHB_FULFILLED) {
try {
this.value = onfulfilled(this.value);
resolve(this.value);
} catch (error) {
reject(this.value);
}
}
//状态为已拒绝(rejected)
if (this.state === PHB_REJECTED) {
try {
this.value = onrejected(this.value);
resolve(this.value);
} catch (error) {
reject(this.value);
}
}
//初始化状态 pending(等待)
if (this.state === PHB_PENDING) {
this.onFulfilled.push(() => {
try {
this.value = onfulfilled(this.value);
resolve(this.value);
} catch (error) {
reject(this.value);
}
});
this.onRejected.push(() => {
try {
this.value = onrejected(this.value);
resolve(this.value);
} catch (error) {
reject(this.value);
}
});
}
});
}
catch(onrejected) {
return this.then(undefined, onrejected);
}
finally(onFinally) {
this.then(onFinally, onFinally);
}
static all(iterable) {
return new PHBPromise((resolve, reject) => {
let value = []; //用于保存成功数据
iterable.forEach(item => {
item.then(
res => {
value.push(res); //成功就保存到数组
if (value.length === iterable.length) {
//全部执行完成就去调用resolve
resolve(value);
}
},
err => {
reject(err); //一个失败直接调用reject
}
);
});
});
}
static allSettled(iterable) {
return new PHBPromise(resolve => {
let value = [];
//allSettled只会执行成功回调
iterable.forEach(item => {
item.then(
res => {
value.push({
status: 'fulfilled', //保存状态,和结果
value: res,
});
if (value.length === iterable.length) {
resolve(value);
}
},
err => {
value.push({
status: 'rejected', //保存状态,和结果
value: err,
});
if (value.length === iterable.length) {
resolve(err);
}
}
);
});
});
}
static any(iterable) {
let isResolve = false; //用于判断一个成功回调执行后其他不会执行
let index = 0;
return new PHBPromise(resolve => {
iterable.forEach(item => {
item.then(
res => {
if (isResolve) return; //如果为true 说明已经执行过resolve 后面的就不需要继续执行
resolve(res);
isResolve = true;
},
err => {
index++;
if (iterable.length === index) {
// AggregateError 把单一的错误集合在一起
resolve(new AggregateError('', 'No Promise in Promise.any was resolved'));
}
}
);
});
});
}
static race(iterable) {
let isCallBack = false; //用于判断一个成功回调执行后其他不会执行
return new PHBPromise((resolve, reject) => {
iterable.forEach(item => {
item.then(
res => {
if (isCallBack) return; // 为true 直接返回
resolve(res);
isCallBack = true;
},
err => {
if (isCallBack) return; // 为true 直接返回
reject(err);
isCallBack = true;
}
);
});
});
}
static resolve(value) {
return new PHBPromise(resolve => {
resolve(value);
});
}
static reject(value) {
return new PHBPromise((undefined, reject) => {
reject(value);
});
}
}