阅读 88

根据PromiseA+实现一个自己的Promise

Promise/A+规范

Promise/A+规范原文: promisesaplus.com/

Promise/A+规范译文: www.ituring.com.cn/article/665…

1. Promise 基本结构

new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('FULFILLED')
  }, 1000)
})
复制代码

构造函数Promise必须接受一个函数作为参数,我们称该函数为handlehandle又包含resolvereject两个参数,它们是两个函数。

定义一个判断一个变量是否为函数的方法,后面会用到

// 判断变量否为function
isFunction(param) {
  return typeof param === 'function';
}
复制代码

首先,我们定义一个名为 MyPromiseClass,它接受一个函数 handle 作为参数

class MPromise {
    constructor(fn) {
        // Do Something
    }

    isFunction(param) {
        return typeof param === 'function';
    }
}
复制代码

再往下看

2. Promise 状态和值

Promise 对象存在以下三种状态:

  • Pending(进行中)
  • Fulfilled(已成功)
  • Rejected(已失败)

状态只能由 Pending 变为 Fulfilled 或由 Pending 变为 Rejected ,且状态改变之后不会在发生变化,会一直保持这个状态。

Promise的值是指状态改变时传递给回调函数的值

上文中handle函数包含 resolvereject 两个参数,它们是两个函数,可以用于改变 Promise 的状态和传入 Promise 的值

new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('FULFILLED')
  }, 1000)
})
复制代码

这里 resolve 传入的 "FULFILLED" 就是 Promise 的值

resolve` 和 `reject
复制代码
  • resolve : 将Promise对象的状态从 Pending(进行中) 变为 Fulfilled(已成功)
  • reject : 将Promise对象的状态从 Pending(进行中) 变为 Rejected(已失败)
  • resolvereject 都可以传入任意类型的值作为实参,表示 Promise 对象成功(Fulfilled)和失败(Rejected)的值

了解了 Promise 的状态和值,接下来,我们为 MyPromise 添加状态属性和值

首先定义三个常量,用于标记Promise对象的三种状态

// 定义Promise的三种状态常量
const PENDING = 'pending'; // 进行中
const FULFILLED = 'fulfilled'; // 已成功
const REJECTED = 'rejected'; // 已失败
复制代码

再为 MyPromise 添加状态和值,并添加状态改变的执行逻辑

// 定义Promise的三种状态常量
const PENDING = 'pending'; // 进行中
const FULFILLED = 'fulfilled'; // 已成功
const REJECTED = 'rejected'; // 已失败

class MPromise {
    // Promise 对象状态
    _status = PENDING;

    constructor(fn) {
        // 初始状态为pending
        this.status = PENDING;
        this.value = null;
        this.reason = null;

        // 执行回调
        try {
            fn(this.resolve.bind(this), this.reject.bind(this));
        } catch (e) {
            this.reject(e);
        }
    }

    // 添加resovle时执行的函数
    resolve(value) {
        if (this.status === PENDING) {
            this.value = value;
            this.status = FULFILLED;
        }
    }
        
        // 添加reject时执行的函数   
    reject(reason) {
        if (this.status === PENDING) {
            this.reason = reason;
            this.status = REJECTED;
        }
    }

    isFunction(param) {
        return typeof param === 'function';
    }
}
复制代码

这样就实现了 Promise 状态和值的改变。下面说一说 Promise 的核心: then 方法

3. Promisethen 方法

Promise 对象的 then 方法接受两个参数:

promise.then(onFulfilled, onRejected)
复制代码

参数可选

onFulfilledonRejected 都是可选参数。

  • 如果 onFulfilledonRejected 不是函数,其必须被忽略

onFulfilled 特性

    如果 onFulfilled 是函数:

  • promise 状态变为成功时必须被调用,其第一个参数为 promise 成功状态传入的值( resolve 执行时传入的值)
  • promise 状态改变前其不可被调用
  • 其调用次数不可超过一次

onRejected 特性

    如果 onRejected 是函数:

  • promise 状态变为失败时必须被调用,其第一个参数为 promise 失败状态传入的值( reject 执行时传入的值)
  • promise 状态改变前其不可被调用
  • 其调用次数不可超过一次

根据上面的规则,我们来为 完善 MyPromise

then(onFulfilled, onRejected) {
        // 检查并处理参数, 之前提到的如果不是function, 就忽略. 这个忽略指的是原样返回value或者reason.
        const fulFilledFn = this.isFunction(onFulfilled) ? onFulfilled : (value) => {
            return value;
        }
        const rejectedFn = this.isFunction(onRejected) ? onRejected : (reason) => {
            throw reason;
        };
            
         // 其调用次数不可超过一次
       switch (this.status) {
            case FULFILLED: {
                fulFilledFn(this.value);
                break;
            }
            case REJECTED: {
                rejectedFn(this.reason);
                break;
            }
        }
    }
复制代码

这样写, 是在then函数被调用的瞬间就会执行. 那这时候如果status还没变成fulfilled或者rejected怎么办, 很有可能还是pending的。

那么我们首先要拿到所有的回调, 然后才能在某个时机去执行他.。新建两个数组, 来分别存储成功和失败的回调, 调用then的时候, 如果还是pending就存入数组。

修改 MPromise: 增加执行队列

// 定义Promise的三种状态常量
const PENDING = 'pending'; // 进行中
const FULFILLED = 'fulfilled'; // 已成功
const REJECTED = 'rejected'; // 已失败

class MPromise {
    // 添加成功回调函数队列
    FULFILLED_CALLBACK_LIST = [];
        // 添加失败回调函数队列
    REJECTED_CALLBACK_LIST = [];
    // Promise 对象状态
    _status = PENDING;

        // .... 省略
}
复制代码

由于 then 方法支持多次调用

let p = new Promise(function(){
    resolve('我是成功');
})
p.then((data) => {console.log(data);},(err) => {});
p.then((data) => {console.log(data);},(err) => {});
p.then((data) => {console.log(data);},(err) => {});


// 输出结果
我是成功
我是成功
我是成功
复制代码

为了实现这样的效果,则上一次的代码将要重新写过,我们可以把每次调用resolve的结果存入一个数组中,每次调用reject的结果存入一个数组。这就是为何会在上面定义两个数组,且分别在resolve()和reject()遍历两个数组的原因。因此,在调用resolve()或者reject()之前,我们在pending状态时,会把多次then中的结果存入数组中,则上面的代码会改变为:

在调用 resolvereject 方法时,需要将队列中存放的回调按照先后顺序依次调用(是不是感觉很像浏览器的事件环机制)。

then(onFulfilled, onRejected) {
    const fulFilledFn = this.isFunction(onFulfilled) ? onFulfilled : (value) => {
        return value;
    }
    const rejectedFn = this.isFunction(onRejected) ? onRejected : (reason) => {
        throw reason;
    };

    switch (this.status) {
        case FULFILLED: {
            fulFilledFn(this.value);
            break;
        }
        case REJECTED: {
            rejectedFn(this.reason);
            break;
        }
          // 我们可以维护两个数组,将每次 then 方法注册时的回调函数添加到数组中,等待执行
        case PENDING: {
            this.FULFILLED_CALLBACK_LIST.push(realOnFulfilled);
            this.REJECTED_CALLBACK_LIST.push(realOnRejected);
            break;
        }
    }
}
复制代码

在status发生变化的时候, 就执行所有的回调。这里咱们用一下es6的getter和setter.。这样更符合语义, 当status改变时, 去做什么事情.。(当然也可以顺序执行, 在给status赋值后, 下面再加一行forEach)

get status() {
    return this._status;
}

set status(newStatus) {
  switch (newStatus) {
    case FULFILLED: {
        this.FULFILLED_CALLBACK_LIST.forEach(callback => {
        callback(this.value);
      });
      break;
    }
    case REJECTED: {
      this.REJECTED_CALLBACK_LIST.forEach(callback => {
            callback(this.reason);
      });
      break;
    }
  }
}
复制代码

多次调用

    then 方法可以被同一个 promise 对象调用多次

  • promise 成功状态时,所有 onFulfilled 需按照其注册顺序依次回调
  • promise 失败状态时,所有 onRejected 需按照其注册顺序依次回调

返回

then 方法必须返回一个新的 promise 对象

promise2 = promise1.then(onFulfilled, onRejected);
复制代码

因此 promise 支持链式调用

promise1.then(onFulfilled1, onRejected1).then(onFulfilled2, onRejected2);
复制代码

检查并处理参数, 之前提到的如果不是function, 就忽略. 这个忽略指的是原样返回value或者reason.

上面的方案,还顺带解决了值穿透的问题。所谓值穿透,就是调用 then 方法时,如果不传入参数,下层链条中的 then 方法还能够正常的获取到 value 或者 reason 值。

new MyPromise(resolve => setTimeout(() => { resolve("Success") }))
.then()
.then()
.then()
...
.then(data => console.log(data));
复制代码

根据上面的规则,我们来为 完善 **MyPromise**

then(onFulfilled, onRejected) {
        // 检查并处理参数, 之前提到的如果不是function, 就忽略. 这个忽略指的是原样返回value或者reason.
      // 上面的方案,还顺带解决了值穿透的问题。所谓值穿透,就是调用 then 方法时,如果不传入参数,下层链条中的 then 方法还能够正常的获取到 value 或者 reason 值。
      const fulFilledFn = this.isFunction(onFulfilled) ? onFulfilled : (value) => {
          return value;
      }
      const rejectedFn = this.isFunction(onRejected) ? onRejected : (reason) => {
          throw reason;
      };
         
     // 规范还规定,then 方法必须返回一个新的 Promise 对象,以实现链式调用。
     const promise2 = new MPromise((resolve, reject) => {
                // 如果 onFulfilled 不是函数且 promise1 成功执行, promise2 必须成功执行并返回相同的值
            const fulfilledMicrotask = () => {
                try {
                    const x = fulFilledFn(this.value);
                    resolve(x)
                } catch (e) {
                    reject(e)
                }
            };
                // 如果 onRejected 不是函数且 promise1 拒绝执行, promise2 必须拒绝执行并返回相同的据因。 
                // 需要注意的是,如果promise1的onRejected执行成功了,promise2应该被resolve
            const rejectedMicrotask = () => {
                try {
                   const x = rejectedFn(this.reason);
                   resolve(x)
                } catch (e) {
                    reject(e);
                }
            }

            switch (this.status) {
                case FULFILLED: {
                    fulfilledMicrotask()
                    break;
                }
                case REJECTED: {
                    rejectedMicrotask()
                    break;
                }
                // 在当前的 Promise 对象(promise1)的状态为 pending 时,将改变 promise2 状态的方法加入到回调函数的队列中。
                case PENDING: {
                    this.FULFILLED_CALLBACK_LIST.push(fulfilledMicrotask)
                    this.REJECTED_CALLBACK_LIST.push(rejectedMicrotask)
                }
            }
        })
        return promise2
}
复制代码

规范规定,then 方法必须返回一个新的 Promise 对象(promise2),新的 promise2 的状态必须依赖于调用 then 方法的 Promise 对象(promise1)的状态,也就是说,必须要等到 promise1 的状态变成 fulfilled 或者 rejected 之后,promise2 的状态才能进行改变。

因此,在 then 方法的实现中,在当前的 Promise 对象(promise1)的状态为 pending 时,将改变 promise2 状态的方法加入到回调函数的队列中。

值的传递

这里涉及到 Promise 的执行规则,包括“值的传递”和“错误捕获”机制:

1、如果 onFulfilled 或者 onRejected 返回一个值 x ,则运行下面的 Promise 解决过程:[[Resolve]](promise2, x)

  • x 不为 Promise ,则使 x 直接作为新返回的 Promise 对象的值, 即新的onFulfilled 或者 onRejected 函数的参数.
  • xPromise ,这时后一个回调函数,就会等待该 Promise 对象(即 x )的状态发生变化,才会被调用,并且新的 Promise 状态和 x 的状态相同。

下面的例子用于帮助理解:

let promise1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve()
  }, 1000)
})
promise2 = promise1.then(res => {
  // 返回一个普通值
  return '这里返回一个普通值'
})
promise2.then(res => {
  console.log(res) //1秒后打印出:这里返回一个普通值
})
let promise1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve()
  }, 1000)
})
promise2 = promise1.then(res => {
  // 返回一个Promise对象
  return new Promise((resolve, reject) => {
    setTimeout(() => {
     resolve('这里返回一个Promise')
    }, 2000)
  })
})
promise2.then(res => {
  console.log(res) //3秒后打印出:这里返回一个Promise
})
复制代码

2、如果 onFulfilled 或者onRejected 抛出一个异常 e ,则 promise2 必须变为失败(Rejected),并返回失败的值 e,例如:

let promise1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('success')
  }, 1000)
})
promise2 = promise1.then(res => {
  throw new Error('这里抛出一个异常e')
})
promise2.then(res => {
  console.log(res)
}, err => {
  console.log(err) //1秒后打印出:这里抛出一个异常e
})
复制代码

3、如果onFulfilled 不是函数且 promise1 状态为成功(Fulfilled)promise2 必须变为成功(Fulfilled)并返回 promise1 成功的值,例如:

let promise1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('success')
  }, 1000)
})
promise2 = promise1.then('这里的onFulfilled本来是一个函数,但现在不是')
promise2.then(res => {
  console.log(res) // 1秒后打印出:success
}, err => {
  console.log(err)
})
复制代码

4、如果 onRejected 不是函数且 promise1 状态为失败(Rejected)promise2必须变为失败(Rejected) 并返回 promise1 失败的值,例如:

let promise1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject('fail')
  }, 1000)
})
promise2 = promise1.then(res => res, '这里的onRejected本来是一个函数,但现在不是')
promise2.then(res => {
  console.log(res)
}, err => {
  console.log(err)  // 1秒后打印出:fail
})
复制代码

根据上面的规则,我们来为 完善 **MyPromise**,实现 resolvePromise 方法

上面的代码,处理了 onFulfilledonRejected 方法的返回值的情况,以及实现了 then 方法的链式调用。

现在考虑一个问题,如果 onFulfilledonRejected 方法返回的是一个 Promise 对象,或者是具有 then 方法的其他对象(thenable 对象),该怎么处理呢?

规范中提到,对于 onFulfilledonRejected 的返回值的,提供一个 Promise Resolution Procedure 方法进行统一的处理,以适应不同的返回值类型。

我们将这个方法命名为 resolvePromise 方法,将其设计为 MyPromise 类上的一个静态方法。

resolvePromise 静态方法的作用,就是根据 onFulfilledonRejected 不同的返回值(x)的情况,来改变 then 方法返回的 Promise 对象的状态。

可以这样理解:我们将改变 promise2 对象的状态的过程,移动到了 resolvePromise 方法中,以便处理更多的细节问题。

下面是 resolvePromise 方法的实现:

    resolvePromise(newPromise, x, resolve, reject) {
        // 如果 newPromise 和 x 指向同一对象,以 TypeError 为据因拒绝执行 newPromise
        // 这是为了防止死循环
        if (newPromise === 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
            x.then((y) => {
                resolvePromise(newPromise, y, resolve, reject);
            }, reject);
        } else if (typeof x === 'object' || this.isFunction(x)) {
            // 如果 x 为对象或者函数
            if (x === null) {
                // null也会被判断为对象
                return resolve(x);
            }

            let then = null;

            try {
                // then 方法可能设置了访问限制(setter),因此这里进行了错误捕获处理
                // 把 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(promise, 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);
        }
    }
复制代码

在实现规范的规程中,这个 resolvePromise 最最难理解的,主要是 return 链这里

if(x instanceof MyPromise){
    // 处理返回值是 Promise 对象的情况
    /**
     * new MyPromise(resolve => {
     *  resolve("Success")
     * }).then(data => {
     *  return new MyPromise(resolve => {
     *    resolve("Success2")
     *  })
     * })
     */
     
      x.then(y => {
        // 用 x 的 fulfilled 后的 value 值 y,去设置 promise2 的状态
        // 上面的注视,展示了返回 Promise 对象的情况,这里调用 then 方法的原因
        // 就是通过参数 y 或者 reason,获取到 x 中的 value/reason

        // 拿到 y 的值后,使用 y 的值来改变 promise2 的状态
        // 依照上例,上面生成的 Promise 对象,其 value 应该是 Success2

        // 这个 y 值,也有可能是新的 Promise,因此要递归的进行解析,例如下面这种情况

        /**
         * new Promise(resolve => {
         *  resolve("Success")
         * }).then(data => {
         *  return new Promise(resolve => {
         *    resolve(new Promise(resolve => {
         *      resolve("Success3")
         *    }))
         *  })
         * }).then(data => console.log(data))
         */

        //  总之,使用 “return”链中最后一个 Promise 对象的状态,来决定 promise2 的状态

        MyPromise.resolvePromise(promise2, y, resolve, reject)
      },reason => {
        reject(reason)
      })
  }
复制代码

最后把then方法的传值方式修改为resolvePromise。

onFulfilled 和 onRejected 是微任务,可以用queueMicrotask包裹执行函数。

事件循环执行到微任务时,会把微任务放入微任务队列,待到执行栈代码执行完毕之后才会执行微软栈中的内容;因此使用了html的微任务apiqueueMicrotask将resolve和reject的回调函数放入微任务队列。

then(onFulfilled, onRejected) {
        const realOnFulfilled = this.isFunction(onFulfilled) ? onFulfilled : (value) => {
            return value
        }
        const realOnRejected = this.isFunction(onRejected) ? onRejected : (reason) => {
            throw reason;
        };
        const promise2 = new MPromise((resolve, reject) => {
            const fulfilledMicrotask = () => {
                // 使用了html的微任务apiqueueMicrotask将resolve和reject的回调函数放入微任务队列。
                queueMicrotask(() => {
                    try {
                        const x = realOnFulfilled(this.value);
                        this.resolvePromise(promise2, x, resolve, reject);
                    } catch (e) {
                        reject(e)
                    }
                })
            };
            const rejectedMicrotask = () => {
                // 使用了html的微任务apiqueueMicrotask将resolve和reject的回调函数放入微任务队列。
                queueMicrotask(() => {
                    try {
                        const x = realOnRejected(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.FULFILLED_CALLBACK_LIST.push(fulfilledMicrotask)
                    this.REJECTED_CALLBACK_LIST.push(rejectedMicrotask)
                }
            }
        })
        return promise2

    }
复制代码

完整源码

const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';

class MPromise {

    FULFILLED_CALLBACK_LIST = [];
    REJECTED_CALLBACK_LIST = [];
    _status = PENDING;
    constructor(fn) {
        // 初始状态为pending
        this.status = PENDING;
        this.value = null;
        this.reason = null;
        try {
            fn(this.resolve.bind(this), this.reject.bind(this));
        } catch (e) {
            this.reject(e);
        }
    }

    get status() {
        return this._status;
    }

    set status(newStatus) {
        this._status = newStatus;
        switch (newStatus) {
            case FULFILLED: {
                this.FULFILLED_CALLBACK_LIST.forEach(callback => {
                    callback(this.value);
                });
                break;
            }
            case REJECTED: {
                this.REJECTED_CALLBACK_LIST.forEach(callback => {
                    callback(this.reason);
                });
                break;
            }
        }
    }

    resolve(value) {
        if (this.status === PENDING) {
            this.value = value
            this.status = FULFILLED
        }
    }

    reject(reason) {
        if (this.status === PENDING) {
            this.reason = reason;
            this.status = REJECTED;
        }
    }

    then(onFulfilled, onRejected) {
        const realOnFulfilled = this.isFunction(onFulfilled) ? onFulfilled : (value) => {
            return value
        }
        const realOnRejected = this.isFunction(onRejected) ? onRejected : (reason) => {
            throw reason;
        };
        const promise2 = new MPromise((resolve, reject) => {
            const fulfilledMicrotask = () => {
                queueMicrotask(() => {
                    try {
                        const x = realOnFulfilled(this.value);
                        this.resolvePromise(promise2, x, resolve, reject);
                    } catch (e) {
                        reject(e)
                    }
                })
            };
            const rejectedMicrotask = () => {
                queueMicrotask(() => {
                    try {
                        const x = realOnRejected(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.FULFILLED_CALLBACK_LIST.push(fulfilledMicrotask)
                    this.REJECTED_CALLBACK_LIST.push(rejectedMicrotask)
                }
            }
        })
        return promise2

    }

    catch (onRejected) {
        return this.then(null, onRejected);
    }

    isFunction(param) {
        return typeof param === 'function';
    }

    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(value) {
        if (value instanceof MPromise) {
            return value;
        }

        return new MPromise((resolve) => {
            resolve(value);
        });
    }

    static reject(reason) {
        return new MPromise((resolve, reject) => {
            reject(reason);
        });
    }

    static race(promiseList) {
        return new MPromise((resolve, reject) => {
            const length = promiseList.length;

            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);
                        });
                }
            }
        });

    }
}

var m1 = new MPromise(function(resolve, reject){  
    resolve('resolve1');  
  }).then(console.log)
复制代码

补充

针对resolve(promise)的情况下,.then底下onFulfilled和onRejected两个回调函数的入参获取情况,修改了一下路白老师的MPromise

    resolve(value) {
        if (this.status === PENDING) {
            const promiseFinish = (promise,self) => {
                promise.then(value=>{
                    self.value = value;self.status = FULFILLED;
                },reason=>{
                    self.reason = reason;self.status = REJECTED;
                })
            }
            value instanceof MPromise 
            ? promiseFinish(value,this)
            : (this.value = value,this.status = FULFILLED)
        }
    }
var m1 = new MPromise(function(resolve, reject){  
    resolve(MPromise.resolve('resolve1'));  
  });  
    
m1.then(  
function fulfilled(value){  
    console.log('fulfilled1: ' + value);  
})
复制代码

参考文章

作者:面条__

链接:juejin.cn/post/684490…

来源:掘金

文章分类
前端
文章标签