亲宝软件园·资讯

展开

JavaScript模拟实现Promise功能的示例代码

菜鸟小于 人气:0

模拟Promise的功能,  按照下面的步骤,一步一步

1. 新建是个构造函数

2. 传入一个可执行函数 函数的入参第一个为 fullFill函数 第二个为 reject函数; 函数立即执行, 参数函数异步执行

3. 状态一旦更改就不可以变更 只能 pending => fulfilled 或者 pending => rejected

4. then 的时候要处理入参的情况 successCallback 和failCallback 均可能为非函数

默认的 failCallback 一定要将异常抛出, 这样下一个promise便可将其捕获 异常冒泡的目的

5. then 中执行回调的时候要捕获异常 将其传给下一个promise

6. catch只是then的一种特殊的写法 方便理解和使用

7. finally 特点

8. Promise.resolve, Promise.reject 根据其参数返回对应的值 或者状态的Promise即可

9. Proise.all 特点

10. Proise.race 特点

const PENDING = 'pending' //等待
const FULFILLED = 'fulfilled' //成功
const REJECTED = 'rejected' //失败

const fulfilledCallback = [] //成功回调函数
const rejectedCallback = []  //失败回调函数

class MyPromise {
   
    constructor (executor) {
        
        try{
            executor(this.resolve, this.reject)
        } catch (e){
            this.reject(e)
        }
    }

    status = PENDING//promise的状态
    value = undefined//成功之后的值
    reason = undefined//失败之后的值
    fulfilledCallback = [] //成功回调函数
    rejectedCallback = []  //失败回调函数
    resolve = value => {
        //如果状态不是等待, 阻止程序继续往下执行
        if(this.status !== PENDING){
            return
        }
        this.status = FULFILLED
        this.value = value
        //判断成功回调是否存在,如果存在, 调用
        // this.fulfilledCallback && this.fulfilledCallback(this.value)
        while(this.fulfilledCallback.length) this.fulfilledCallback.shift()()

    }
    reject = reason => {
        //如果状态不是等待, 阻止程序继续往下执行
        if(this.status !== PENDING){
            return
        }
        this.status = REJECTED
        this.reason = reason
        //判断失败回调是否存在,如果存在, 调用
        // this.rejectedCallback && this.rejectedCallback(this.reason)
        while(this.rejectedCallback.length) this.rejectedCallback.shift()()
    }
    then = (fulfilledCallback, rejectedCallback) => {
        fulfilledCallback = fulfilledCallback ? fulfilledCallback : value => value
        rejectedCallback = rejectedCallback ? rejectedCallback : reason => {throw reason}
        let promise2 = new MyPromise((resolve, reject) => {
            
            //判断状态
            if(this.status === FULFILLED){
                setTimeout(() => {
                    try {
                        //判断x 传过来的可能是promise,先查看promise返回的结果,在决定是用resolve还是reject,
                        //如果是普通值,直接调用resolve
                        let x = fulfilledCallback(this.value)
                        //外面加载完,才能获取到promise2,用异步解决
                        resolvePromise(promise2,x,resolve, reject)
                    } catch (error) {
                        reject(error)
                    }
                    
                },0)
               
            }else if(this.status === REJECTED){
                
                setTimeout(() => {
                    try {
                        //判断x 传过来的可能是promise,先查看promise返回的结果,在决定是用resolve还是reject,
                        //如果是普通值,直接调用resolve
                        let x = rejectedCallback(this.reason)
                        //外面加载完,才能获取到promise2,用异步解决
                        resolvePromise(promise2,x,resolve, reject)
                    } catch (error) {
                        reject(error)
                    }
                    
                },0)
            }else{
                //等待状态
                this.fulfilledCallback.push(() => {
                    setTimeout(() => {
                        try {
                            //判断x 传过来的可能是promise,先查看promise返回的结果,在决定是用resolve还是reject,
                            //如果是普通值,直接调用resolve
                            let x = fulfilledCallback(this.value)
                            //外面加载完,才能获取到promise2,用异步解决
                            resolvePromise(promise2,x,resolve, reject)
                        } catch (error) {
                            reject(error)
                        }
                        
                    },0)
                });
                this.rejectedCallback.push(() => {
                    setTimeout(() => {
                        try {
                            //判断x 传过来的可能是promise,先查看promise返回的结果,在决定是用resolve还是reject,
                            //如果是普通值,直接调用resolve
                            let x = rejectedCallback(this.reason)
                            //外面加载完,才能获取到promise2,用异步解决
                            resolvePromise(promise2,x,resolve, reject)
                        } catch (error) {
                            reject(error)
                        }
                        
                    },0)
                });
            }
        })
        return promise2
    }

    static all (array) {
        let result= []
        let index = 0;

        return new MyPromise((resolve, reject) => {

            function addData (key, value) {
                result[key] = value
                index++
                if (index === array.length) {
                    resolve(result)
                }
            }

            for (let i = 0; i < array.length; i++) {
                
                if (array[i] instanceof MyPromise) {
                    //promise对象
                    array[i].then(value => addData(i, value), reason => reject(reason))
                } else {
                    //普通值, 放到数组里
                    addData(i, array[i])
                }
            }
        })

    }

    static resolve (value) {
        if(value instanceof MyPromise) return value
        return new MyPromise(resolve => resolve(value))

    }

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

    }

    catch (rejectedCallback) {
        return this.then(undefined, rejectedCallback)
    }

}

function resolvePromise(promise2,x,resolve, reject){

    if(x === promise2){
        return reject(new TypeError('啦啦啦啦'))
    }
    if(x instanceof MyPromise){
        //是promise
        //往下直接传
        x.then(resolve,reject)
    }else{
        //普通值
        resolve(x)
    }
}

module.exports = MyPromise;

加载全部内容

相关教程
猜你喜欢
用户评论