const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
class MyPromise {
constructor (executor) {
this._status = PENDING;
this._value = undefined;
this._resolveQueue = [];
this._rejectQueue = [];
let _resolve = (val) => {
const run = () => {
if (this._status !== PENDING) return;
this._status = FULFILLED;
this._value = val;
while (this._resolveQueue.length) {
const callback = this._resolveQueue.shift();
callback(val);
}
};
setTimeout(run);
};
let _reject = (val) => {
const run = () => {
if (this._status !== PENDING) return;
this._status = REJECTED;
this._value = val;
while (this._rejectQueue.length) {
const callback = this._rejectQueue.shift();
callback(val);
}
};
setTimeout(run);
};
executor(_resolve, _reject);
}
then (resolveFn, rejectFn) {
typeof resolveFn !== 'function' ? resolveFn = value => value : null;
typeof rejectFn !== 'function' ? rejectFn = reason => {
throw new Error(reason instanceof Error ? reason.message : reason);
} : null;
return new MyPromise((resolve, reject) => {
let fulfilledFn = (val) => {
try {
let x = resolveFn(val);
x instanceof MyPromise ? x.then(resolve, reject) : resolve(x);
} catch (e) {
reject(e);
}
};
let rejectedFn = (error) => {
try {
let x = rejectFn(error);
x instanceof MyPromise ? x.then(resolve, reject) : resolve(x);
} catch (error) {
reject(error);
}
};
switch (this._status) {
case FULFILLED:
fulfilledFn(this._value);
break;
case REJECTED:
rejectedFn(this._value);
break;
case PENDING:
this._resolveQueue.push(fulfilledFn);
this._rejectQueue.push(rejectedFn);
break;
}
});
};
catch (rejectFn) {
return this.then(undefined, rejectFn);
}
finally (callback) {
return this.then(
value => MyPromise.resolve(callback()).then(() => value),
reason => MyPromise.resolve(callback()).then(() => {
throw reason;
}));
}
static resolve (value) {
if (value instanceof MyPromise) return value;
return new MyPromise((resolve) => resolve(value))
}
static reject (reason) {
return new MyPromise((resolve, reject) => reject(reason))
}
static all (promiseArr) {
let index = 0;
let result = [];
return new MyPromise((resolve, reject) => {
promiseArr.forEach((p, i) => {
MyPromise.resolve(p).then(
val => {
result[i] = val;
index++;
if (index === promiseArr.length) {
resolve(result);
}
},
err => {
reject(err);
});
});
});
}
static race (promiseArr) {
return new MyPromise((resolve, reject) => {
for (let p of promiseArr) {
MyPromise.resolve(p).then(
val => {
resolve(val);
},
err => {
reject(err);
});
}
});
}
}
//
// new MyPromise((resolve, reject) => {
// resolve('kkk')
// })
// .then(result => {
// console.log(result);
// return MyPromise.reject('reject')
// })
// .catch(error => {
// console.log(error);
// return 'jjj'
// })
// .finally((res) => {
// console.log(666);
// console.log(res);
// return 'rr'
// }).then(res => {
// console.log(999);
// console.log(res);
// });
let sss = MyPromise.race([new MyPromise(resolve => {
setTimeout(() => {
resolve(6666)
}, 1000)
}), 11, MyPromise.resolve(66), new MyPromise(resolve => {
setTimeout(() => {
resolve(999)
})
})]).then(res => {
console.log(res);
});
参考文档:
https://juejin.im/post/6844904096525189128 (9k字 | Promise/async/Generator实现原理解析)
https://juejin.im/post/6844903922964889608#heading-4 (手写Promise)
https://www.icode9.com/content-4-365156.html (Promise A+ 规范【中文版】)
https://juejin.cn/post/6844903607968481287#heading-0 (Promise不会??看这里!!!史上最通俗易懂的Promise!!!)