states
- pending
- fulfilled
- rejected pending为初始状态,状态只能被改变一次,即改为fulfilled或者rejected后无法在被修改。状态改变时需传参value或者reason,不传则为undefind。
const PENDING='pending'
const FULFILLED='fulfilled'
const REJECTED='rejected'
init
onFulfilledCallBackList和onRejectedCallBackList用来存储多个fulfilled和rejected回调;
class MPromise{
onFulfilledCallBackList=[]
onRejectedCallBackList=[]
constructor(fn){
//fulfilled返回值
this.value=null
//rejected返回值
this.reason=null
//初始状态
this.status=PENDING
// try catch 捕获执行异常
try{
// bind指向自身this
fn(this.resolve.bind(this),this.reject.bind(this))
}catch(error){
this.reject(e)
}
}
//判断是否为函数
isFunction(param){
return typeof param === 'function'
}
}
resolve
resolve(value){
if(this.status==PENDING){
this.value=value
}
}
rejected
reject(reason){
if(this.status==PENDING){
this.reason=reason
}
}
监听status变化执行回调函数
_status=PENDIND
get status(){
return this._status
}
set status(newStatus){
this._status=newStatus
switch (newStatus) {
case FULFILLED: {
this.onFulfilledCallBackList.forEach(callback => {
callback(this.value)
})
break;
}
case REJECTED: {
this.onRejectedCallBackList.forEach(callback => {
callback(this.reason)
})
break;
}
}
}
then
- then方法应该有两个传参onFulfilled和onRejected,必须是函数类型,否则忽略;
- onFulfilled和onRejected应该是一个微任务,需状态改变为fulfilled或者rejected才执行且只执行一次;
- then方法可以多次调用,在初始化时已设置两个数组用来存放;
- then返回的是一个Promise;
then(onFulfilled,onRejected){
//判断是否为函数
const realFulfilled = this.isFunction(onFulfilled) ? onFulfilled : value=>value;
const realRejected = this.isFunction(onRejected) ? onRejected : reason=>{ return throw(reason) };
//返回一个promise
const promise2=new MPromise((resolve,reject)=>{
const fulfilledMicroTask = ()=>{
try{
//用queueMicrotask微任务包裹
queueMicrotask(()=>{
const x=realFulfilled(this.value)
//待实现
this.resolvePromise(promise2,x,resolve,reject)
})
}catch(e){
reject(e)
}
}
const rejectedMicroTask = ()=>{
try{
//用queueMicrotask微任务包裹
queueMicrotask(()=>{
const x=realRejected(this.reason)
//待实现
this.resolvePromise(promise2,x,resolve,reject)
})
}catch(e){
reject(e)
}
}
switch (this.status) {
case FULFILLED: {
fulfilledMicroTask()
break;
}
case REJECTED: {
rejectedMicroTask()
break;
}
case PENDING: {
this.onFulfilledCallBackList.push(fulfilledMicroTask)
this.onRejectedCallBackList.push(rejectedMicroTask)
}
}
})
return promise2
}
catch
catch(onRejected){
this.then(null,onRejected)
}
resolvePromise
resolvePromise是对then传入的函数执行后的再次处理
resolvePromise(promise2, x, resolve, reject) {
// 如果 newPromise 和 x 指向同一对象,以 TypeError 为据因拒绝执行 newPromise
// 这是为了防止死循环
if (promise2 === x) {
return reject(new TypeError('The promise and the return value are the same'));
}
if (x instanceof MPromise) {
// 如果 x 为 Promise ,则使 newPromise 接受 x 的状态
// 也就是继续执行x,如果执行的时候拿到一个y,还要继续解析y
queueMicrotask(() => {
x.then((y) => {
this.resolvePromise(promise2, y, resolve, reject);
}, reject);
})
} else if (typeof x === 'object' || this.isFunction(x)) {
// 如果 x 为对象或者函数
if (x === null) {
// null也会被判断为对象
return resolve(x);
}
let then = null;
try {
// 把 x.then 赋值给 then
then = x.then;
} catch (error) {
// 如果取 x.then 的值时抛出错误 e ,则以 e 为据因拒绝 promise
return reject(error);
}
// 如果 then 是函数
if (this.isFunction(then)) {
let called = false;
// 将 x 作为函数的作用域 this 调用
// 传递两个回调函数作为参数,第一个参数叫做 resolvePromise ,第二个参数叫做 rejectPromise
try {
then.call(
x,
// 如果 resolvePromise 以值 y 为参数被调用,则运行 resolvePromise
(y) => {
// 需要有一个变量called来保证只调用一次.
if (called) return;
called = true;
this.resolvePromise(promise2, y, resolve, reject);
},
// 如果 rejectPromise 以据因 r 为参数被调用,则以据因 r 拒绝 promise
(r) => {
if (called) return;
called = true;
reject(r);
});
} catch (error) {
// 如果调用 then 方法抛出了异常 e:
if (called) return;
// 否则以 e 为据因拒绝 promise
reject(error);
}
} else {
// 如果 then 不是函数,以 x 为参数执行 promise
resolve(x);
}
} else {
// 如果 x 不为对象或者函数,以 x 为参数执行 promise
resolve(x);
}
static resolve
static resolve(value) {
if (value instanceof MPromise) {
return value;
}
return new MPromise((resolve) => {
resolve(value);
});
}
static reject
static reject(reason) {
return new MPromise((resolve, reject) => {
reject(reason);
});
}
static race
static race(iterator) {
let promiseList = Array.from(iterator)
const length = promiseList.length;
return new MPromise((resolve, reject) => {
if (length === 0) {
return resolve();
} else {
for (let i = 0; i < length; i++) {
MPromise.resolve(promiseList[i]).then(
(value) => {
return resolve(value);
},
(reason) => {
return reject(reason);
});
}
}
});
}
}
static all
static all(iterator) {
return new MPromise((resolve, reject) => {
let promiseList = Array.from(iterator)
let length = promiseList.length;
let resList = []
let count = 0
if (length == 0) {
resolve()
} else {
promiseList.forEach((promise, index) => {
MPromise.resolve(promise).then(res => {
count++
resList[index] = res
if (length == count) {
resolve(resList)
}
}).catch(e => { reject(e) })
})
}
})
}