一步步实现Promise
实现了但没完全实现。。。
使用的ES6的class方式实现的。
参考掘金作者Sunshine_Lin的实现,链接在本文末尾。
实现构造器
要点:
- promise有三个状态,分别是
pending fulfilled rejected
,所以实例需要一个保存这个状态的变量。 - promise需要保存执行后的结果,又需要一个变量保存。
- 执行器exec里报错时,抛出异常,promise需要变为
rejected
状态
实现:
class MyPromise {
constructor(exec) {
this.promiseResult = undefined;
this.promiseState = 'pending';
try {
exec(this.resolve, this.reject);
} catch (e) {
this.reject(e)
}
}
}
实现resolve和reject
要点:
- promise由
pending
变为fulfilled
或者rejected
后,就settle
了不会再变了 - 要将resolve和reject的this绑定,防止跟随执行环境发生变化
实现:
class MyPromise {
constructor(exec) {
// ...
}
resolve = (value) => {
if (this.promiseState === 'pending') {
this.promiseResult = 'fulfilled'
this.promiseState = value;
}
}
reject = (reason) => {
if (this.promiseState === 'pending') {
this.promiseResult = 'rejected';
this.promiseState = reason;
}
}
}
实现同步的then
要点:
- 因为then的两个参数可以省略,所以需要判断并设置默认值
- 根据promise的状态执行then的不同的函数
实现:
class MyPromise {
// ...
then = (onFulfilled, onRejected) => {
// 因为then的两个参数可以省略,所以需要判断
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : val => val;
onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason };
if (this.promiseState === 'fulfilled') {
onFulfilled(this.promiseResult)
}
if (this.promiseState === 'rejected') {
onRejected(this.promiseResult)
}
}
}
同步的then,无法处理异步任务中的resolve和reject,因为同步执行时promiseState
还在pending
状态。不会执行onFulfilled或者onRejected函数。
实现异步的then
如何保证then方法是在resolve或这reject后才执行?
还需要在then做功夫,既然同步执行时promiseState
还在pending
状态,就再加一个if判断,当promise状态为pending
时执行then,则将当前then方法传入的的onFulfilled
函数和onRejected
函数放入promise实例的所维护的数组中(我发现使用一个变量保存一个函数就可以,想不到为啥用数组,难道有多次then,而且第二次then时,promise还是pending
状态?有这种场景???)。
放入数组的函数,在resolve或者reject真正执行的时候,才会被执行,此时就拿出数组的onFulfilled
函数和onRejected
函数,依次执行。
要点:
- 添加实例变量,保存在promise为
pending
状态时,then被调用时传入的函数参数 - 在resolve和reject内调用这些方法。
实现:
class MyPromise {
constructor(exec) {
this.promiseResult = undefined;
this.promiseState = 'pending';
// this.onFulFilledCallback = [];
// this.onRejectedCallback = [];
// 好像不用数组也行...
this.onFulFilledCallback = null;
this.onRejectedCallback = null;
try {
exec(this.resolve, this.reject);
} catch (e) {
this.reject(e)
}
}
resolve = (value) => {
if (this.promiseState === 'pending') {
this.promiseState = 'fulfilled'
this.promiseResult = value;
// console.log(this.onFulFilledCallback.length);
// this.onFulFilledCallback.shift()(value)
if (this.onFulFilledCallback) {
this.onFulFilledCallback(value)
}
}
}
reject = (reason) => {
if (this.promiseState === 'pending') {
this.promiseState = 'rejected';
this.promiseResult = reason;
if (this.onRejectedCallback) {
this.onRejectedCallback(reason)
}
}
}
then = (onFulfilled, onRejected) => {
// 因为then的两个参数可以省略,所以需要判断
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : val => val;
onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason };
if (this.promiseState === 'fulfilled') {
onFulfilled(this.promiseResult);
}
if (this.promiseState === 'rejected') {
onRejected(this.promiseResult);
}
if (this.promiseState === 'pending') {
// this.onFulFilledCallback.push(onFulfilled);
// this.onRejectedCallback.push(onRejected);
this.onFulFilledCallback = onFulfilled;
this.onRejectedCallback = onRejected;
}
}
}
实现可链式调用的then
要点:
- then会返回一个新的promise实例
- 原来的then的处理需要“通知”到新的promise实例
- 如果then的函数参数的返回值是promise,那么新的promise实例返回的状态取决于这个promise
- 如果返回值非promise,新promise对象就是fulfilled,且值为此返回值
实现:
class MyPromise {
constructor(exec) {
this.promiseResult = undefined;
this.promiseState = 'pending';
this.onFulFilledCallback = [];
this.onRejectedCallback = [];
try {
exec(this.resolve, this.reject);
} catch (e) {
this.reject(e)
}
}
resolve = (value) => {
console.log('resolve: ', value, ' | ', this.onFulFilledCallback);
if (this.promiseState === 'pending') {
this.promiseState = 'fulfilled'
this.promiseResult = value;
while (this.onFulFilledCallback.length) {
console.log('this.onFulFilledCallback.length: ', this.onFulFilledCallback.length);
this.onFulFilledCallback.shift()(this.promiseResult)
}
}
}
reject = (reason) => {
if (this.promiseState === 'pending') {
this.promiseState = 'rejected';
this.promiseResult = reason;
while (this.onRejectedCallback.length) {
this.onRejectedCallback.shift()(this.promiseResult)
}
}
}
then = (onFulfilled, onRejected) => {
// 因为then的两个参数可以省略,所以需要判断并设置默认值
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : val => val;
onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason };
// 放到thenPromise里了
// if (this.promiseState === 'fulfilled') {
// onFulfilled(this.promiseResult);
// }
// if (this.promiseState === 'rejected') {
// onRejected(this.promiseResult);
// }
// if (this.promiseState === 'pending') {
// this.onFulFilledCallback.push(onFulfilled);
// this.onRejectedCallback.push(onRejected);
// }
let thenPromise = new MyPromise((res, rej) => {
// console.log(this.promiseState);
// 此函数是一个箭头函数,exec也是箭头函数,所以resolvePromise声明时就会绑定到外面的promise,而不是这个promise
const resolvePromise = tt => {
try {
// 这个this是外面的,而不是这个新建的MyPromise的
const x = tt(this.promiseResult); // 执行tt函数,拿到函数执行的结果,根据此结果进行判断。
if (x === this.thenPromise) { // 这个判断不懂。。。
throw new Error("then返回一个新的promise而不是自身")
}
if (x instanceof MyPromise) {
// console.log('here');
x.then(res, rej);
} else {
// 非promise时primise实例就是调用resolve的fulfilled的
res(x);
}
} catch (err) {
rej(err)
}
}
if (this.promiseState === 'fulfilled') {
// onFulfilled(this.promiseResult);
resolvePromise(onFulfilled);
}
if (this.promiseState === 'rejected') {
// onRejected(this.promiseResult);
resolvePromise(onRejected);
}
// resolve或者reject是被异步调用的
if (this.promiseState === 'pending') {
this.onFulFilledCallback.push(() => {
resolvePromise(onFulfilled)
});
this.onRejectedCallback.push(() => {
resolvePromise(onRejected)
});
}
})
return thenPromise;
}
}
参考链接
https://juejin.cn/post/6994594642280857630