手写Promise

整体思路:

  • 1.通过new Promise(),得知Promise是一个类
  • 2.创建Promise需要一个执行方法,并且在构造时,立即调用该执行器
  • 3.promise有三种状态:等待(pending)、成功(fulfilled)、失败(rejected)
    • 但只有两条路线可选,要么成功,要么失败,一旦确定状态,便不可更改
      • 等待(pending)-> 成功(fulfilled)
      • 等待(pending)-> 失败(rejected)
  • 4.resolve 和 reject 用来更改状态的,需要在构造Promise时传递给调用者使用
    • resolve : fulfilled
    • reject: rejected
  • 5.then 分别处理 成功状态 和 失败状态 下的回调方法方法。并需要传递对应的值。且该方法是定义在原型对象中的
  • 6.异步执行resolve和reject时,Promise中拿到的状态是pending值,所以无法去调用resolve 或 reject方法
  • 7.Promise可以多次调用then()方法,同时需返回多次结果
  • 8.Promise具有链式调用的情况,链式调用拿到的都是全新的Promise对象
  • 9.链式调用中,识别到调用到了promise自己本身时,需报错
  • 10.捕获执行器、链式调用中的异常情况
  • 11.then()方法的参数是可选的:如果then()方法里没有参数,其运行方式应该是把上一次的返回的结果,传递给下一个then()

相关的方法实现:

    1. Promise.all([])
    • all()方法是静态的
    • all(array)方法传递的是数组,数组中可以是普通值,也可以是Promise对象
    • 整个方法按照数组的顺序执行,数组中有异步操作,需等待异步操作执行完后,才能结束方法
    • all(array)方法返回的也是Promise对象
    • all(array)方法的数组参数中,有一个失败,则整体都失败
    1. Promise.resolve()
    • 该方法是静态的
    • 若传入的参数是Promise对象,则返回该对象
    • 若传入的参数是普通值,则新建Promise对象,再返回
    1. finally()
    • 该方法是Promise原型上的
    • 无论上一步操作是否成功,都会执行该方法
    • finally()返回的是Promise对象
    • finally()里的方法有异步操作时,等待该操作结束
    1. catch()
    • 该方法是Promise原型上的
    • catch()返回的是Promise对象
    • 为了捕获异常

创建

(MyPromise.js)

//状态常量(可提示、可重用)
const PENDING = "pending" //等待
const FULFULLED = "fulfilled" //成功
const REJECTED = "rejected" //失败

//promise是个类
class MyPromise {
    //状态,默认为等待
    status = PENDING

    //成功状态下的值
    value = undefined

    //失败状态下的原因
    reason = undefined

    //成功回调需要用数组将回调函数组装起来
    successCallback = []

    //失败回调需要用数组将回调函数组装起来
    failCallback = []

    //创建promise时,需要一个执行器executor,该执行器需要将resolve和reject方法传递过去,供调用者使用。并立即调用该执行器
    constructor(executor) {
        //捕获执行器中的异常,并给到reject中
        try {
            executor(this.resolve, this.reject)
        } catch (err) {
            this.reject(err)
        }
    }

    //修改状态为 成功
    resolve = (value) => {//使用箭头函数是为了将this指向Promise

        //判断状态是否已改变。若已改变,则不能修改
        if (this.status !== PENDING) return;

        this.status = FULFULLED
        this.value = value

        //循环执行成功回调数组里的函数
        while (this.successCallback.length) {
            //shift()方法:删除数组中的第一个值,并返回该值
            this.successCallback.shift()(this.value)
        }
    }

    //修改状态为 失败
    reject = (reason) => {

        //判断状态是否已改变。若已改变,则不能修改
        if (this.status !== PENDING) return;

        this.status = REJECTED
        this.reason = reason

        //循环执行失败回调数组里的函数
        while (this.failCallback.length) {
            //shift()方法:删除数组中的第一个值,并返回该值
            this.failCallback.shift()(this.reason)
        }
    }

    //调用Promise处理结果
    then(successCallback, failCallback) {

        //判断then()方法中是否有参数
        successCallback = successCallback ? successCallback : value => value
        failCallback = failCallback ? failCallback : reason => { throw reason }

        // 链式调用时,then()方法返回的是全新的promise对象
        // 在这里需要创建一个新的promise对象
        let newPromise = new MyPromise((resolve, reject) => {

            //判断状态
            if (this.status === FULFULLED) {//状态为成功

                //按照javascript的代码执行流程,此处是获取不到newPromise对象,需要将整个代码块进行异步操作处理
                setTimeout(() => {

                    //在then()方法的resolve函数中发生异常,需要在调用resolve函数时捕获异常
                    try {

                        //then()里的有返回值时,此处是可以接受到的
                        //并且反馈给新的promise对象中的resolve
                        let retValue = successCallback(this.value)

                        //判断返回值是否为当前对象或promise实例
                        resolvePromise(newPromise, retValue, resolve, reject)
                    } catch (err) {
                        reject(err)
                    }
                }, 0)

            } else if (this.status === REJECTED) {//状态为失败
                setTimeout(() => {
                    try {
                        let retValue = failCallback(this.reason)

                        resolvePromise(newPromise, retValue, resolve, reject)
                    } catch (err) {
                        reject(err)
                    }
                }, 0)

            } else {//针对异步情况下,其状态为等待,需对其回调方法做保存

                this.successCallback.push(() => {
                    setTimeout(() => {

                        //在异步操作情况下,处理异常情况
                        try {
                            let retValue = successCallback(this.value)

                            resolvePromise(newPromise, retValue, resolve, reject)
                        } catch (err) {
                            reject(err)
                        }
                    }, 0)
                })
                this.failCallback.push(() => {
                    setTimeout(() => {
                        try {
                            let retValue = failCallback(this.reason)

                            resolvePromise(newPromise, retValue, resolve, reject)
                        } catch (err) {
                            reject(err)
                        }
                    }, 0)
                })
            }
        })
        return newPromise
    }

    /**
     * 该方法是Promise原型上的
     * 无论上一步操作是否成功,都会执行该方法
     * finally()返回的是Promise对象
     * finally()里的方法有异步操作时,等待该操作结束
     */
    finally(callback) {
        //判断上一步操作是否成功,可以使用then()
        return this.then(value => {
            return MyPromise.resolve(callback()).then(() => value)

        }, reason => {
            return MyPromise.resolve(callback()).then(() => { throw reason })
        })
    }

    /**
     * 该方法是Promise原型上的
     * catch()返回的是Promise对象
     * 为了捕获异常
     */
    catch(failCallback) {
        return this.then(undefined, failCallback)
    }

    /**
     * all()方法是静态的
     * all(array)方法传递的是数组,数组中可以是普通值,也可以是Promise对象
     * 整个方法按照数组的顺序执行,数组中有异步操作,需等待异步操作执行完后,才能结束方法
     * all(array)方法返回的也是Promise对象
     * all(array)方法的数组参数中,有一个失败,则整体都失败
     */
    static all(array) {
        let result = []
        let index = 0//已执行个数。为等待异步操作结束

        return new MyPromise((resolve, reject) => {
            for (let i = 0; i < array.length; i++) {
                let current = array[i]

                /**将值放入result中 */
                function addValue(idx, value) {

                    index++
                    result[idx] = value

                    //如果 result数组中的数量 不等于 参数数组中的数量,继续等待异步操作执行
                    if (index === array.length) {
                        resolve(result)
                    }
                }

                //判断数组成员的类型
                if (current instanceof MyPromise) {//MyPromise实例

                    //Promise对象,需要执行该Promise对象,然后将值放入result中
                    current.then(value => {

                        //执行成功,将返回结果放入result中
                        addValue(i, value)
                    }, reason => {

                        //执行失败,结束当前promise,并返回失败信息
                        reject(reason)
                    })
                } else {//普通值
                    addValue(i, current)
                }
            }
        })
    }

    /**将参数快速组成Promise对象,然后返回 
     * 该方法是静态的
     * 若传入的参数是Promise对象,则返回该对象
     * 若传入的参数是普通值,则新建Promise对象,再返回
    */
    static resolve(value) {

        //判断是否是Promise对象
        if (value instanceof MyPromise) return value;

        return new MyPromise((resolve, reject) => resolve(value))
    }
}

/**解析值的状态,并调用不同的方法 */
function resolvePromise(currPromise, value, resolve, reject) {

    if (value instanceof MyPromise) {//promise实例

        //根据该promise实例的不同结果状态,调用不同方法
        if (currPromise === value) {
            return reject(new TypeError("循环调用,报错,报错,报错!"))
        }
        value.then(resolve, reject)
    } else {//普通值
        resolve(value)
    }
}

//node环境下使用module.exports将对象抛出去
module.exports = MyPromise
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值