浅谈Promise的实现

这两天在看promise,分享一下自己的心得

Promise主要用于异步处理,用来解决传统的回调地狱问题。
它是把异步处理规范起来,采用统一的接口来编写,使得更规范化。
在实际项目中可以用来处理异步函数,以及多个异步操作的处理,在
异步处理中定义异步方法(如ajax),在.then方法中处理结果,使得
逻辑更清晰,更易于维护,而不是使用函数嵌套函数的方式。
Promise提供了all方法来处理多个异步程序全部调用完成后返回结果,
还提供了与之相对的race方法.
promise链式调用:会将前一个then的返回值(return)作为下一次
成功的回调函数的参数。

那么,如何实现一个promise呢 ? 话不多说,直接上代码:

/**
 * 实现一个Promise
 */
function Promise(task) {
    //接收一个处理函数
    let that = this;//缓存this
    //promise有三种状态  默认为pending
    that.status = 'pending';
    that.onFulfilledFns = [];//所有成功的回调
    that.onRejectedFns = [];//所有失败的回调
    that.value = undefined;
    function resolve(value) {
        //成功函数
        if(that.status == 'pending'){
            that.status = 'fulfilled';
            that.value = value;
            //执行所有成功的回调
            that.onFulfilledFns.forEach(item=>item(value));
        }
    };
    function reject(reason) {
        //失败函数
        if(that.status == 'pending'){
            that.status = 'rejected';
            that.value = reason;
            //执行所有失败的回到
            that.onRejectedFns.forEach(item=>item(reason));
        }
    };
    //立即执行传入的处理函数
    try{
        task(resolve,reject);
    }catch (err){
        reject(err)
    }
};
function resolvePromise(promise2,x,resolve,reject) {
    let then;
    if(promise2 === x){
        return reject(new Error('循环引用'));
    }
    if(x instanceof Promise){
        //判断x的prototype所指向的对象是否存在Promise的原型链上
        if(x.status= 'pending'){
            x.then(function (y) {
                //递归 调用
                resolvePromise(promise2,y,resolve,reject);
            },reject)
        }else if(x.status == 'fulfilled'){
            resolve(x.value);
        }else if(x.status == 'rejected'){
            reject(x.value);
        }
    }else if(x != null && typeof x == 'object' || typeof x == 'function'){
        try{
            then = x.then;
            if(typeof then == 'function'){
                then.call(x,function (y) {
                   resolvePromise(promise2,y,resolve,reject);
                },function (y) {
                    reject(y)
                });
            }
        }catch (e){
            reject(e);
        }
    }else{
        resolve(x);
    }
}
//then方法
Promise.prototype.then = function (onFulfilled, onRejected) {
    //假如没有传入异步处理程序则直接返回结果
    onFulfilled = typeof onFulfilled == 'function'?onFulfilled:function (value) {
        return value;
    };
    onRejected = typeof onRejected == 'function'?onRejected:function (reason) {
        return reason;
    };
    var promise2;//用来实现链式调用
    let that = this;
    if(that.status == 'fulfilled'){
        promise2 = new Promise(function (resolve,reject) {
            let x = onFulfilled(that.value);
            resolvePromise(promise2,x,resolve,reject);
        });
    }else if(that.status == 'rejected'){
        promise2 = new Promise(function (resolve,reject) {
            let x = onRejected(that.value);
            reject(x);
        });
    }else if(that.status == 'pending'){
        promise2 = new Promise(function (resolve,reject) {
            that.onFulfilledFns.push(function(){
                let x = onFulfilled(that.value);
                resolve(x);
            });
            that.onRejectedFns.push(function () {
                let x = onRejected(that.value);
                reject(x);
            });
        });
    }else{
        promise2 = new Promise(function (resolve,reject) {
            reject('Promise内部状态错误');
        });
    }
    return promise2;
};
Promise.resolve = function (val) {
    return new Promise(function (resolve,reject) {
        resolve(val);
    });
};
Promise.reject = function (val) {
    return new Promise(function (resolve,reject) {
        reject(val);
    });
};
Promise.all = function (arrs) {
    //all方法接收一个promise数组,数组中所有异步操作结束后返回一个新的promise
    if(typeof arrs == 'object' && arrs.length > 0){
        return new Promise(function (resolve,reject) {
            let result = [];//新的promise返回结果
            let indexNum = 0;//当前完成几个
            let resolved = function (index) {
                return function (data) {
                    result[index] = data;
                    indexNum++;
                    if(indexNum == arrs.length){
                        resolve(result);
                    }
                }
            };
            for(let i=0;i<arrs.length;i++){
                arrs[i].then(resolved(i),function (reason) {
                    reject(reason);
                });
            };
        });
    }else{
        return new Promise(function (resolve,reject) {
            reject(new Error('all方法传入参数错误'));
        });
    }
};
Promise.race = function (arrs) {
    if(typeof arrs == 'object' && arrs.length > 0){
        return new Promise(function (resolve,reject) {
            for(let i=0;i<arrs.length;i++){
                arrs[i].then(function (data) {
                    resolve(data);
                },function (err) {
                    reject(err);
                });
            };
        });
    }else{
      return new Promise(function (resolve,reject) {
          reject(new Error('race方法传入参数错误'));
      })
    };
};

module.exports = Promise;

//实现了Promise.all Promise.race Promise.reject以及Promise.resolve方法

欢迎指正交流!



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值