模擬實現Promise

最近複習了一下Promise,決定自己實現一下,加深對Promise流程的理解。當然,這個模擬還不是很完善,比如把events放在了原型上,這個會導致新的MyPromise也受到影響。
/**
 * 使用MyPromise模擬Promise基本功能:
 * MyPromise新建就立即執行其參數fn,這點比較重要
 * fn裏面必須調用狀態函數resolve或者reject之一
 * 每次.then接受一個處理MyPromise當前狀態的回調函數,包括resolve和reject(都是異步執行)
 * 回調函數裏面默認或者顯式返回一個新的MyPromise,之後的then中的回調是處理新的MyPromise的狀態
 * 每次resolve或者reject執行就形成了一個新的MyPromise(並立即執行),後續的then會處理其狀態,這樣就保證默認的狀態不會改變
 *
 * 使用MyPromise.prototype.events保存時間,其實then鏈是最先執行的
 * 每次resolve或者reject都會使得events中的第一個回調出隊列
 *
 * @param fun
 * @constructor
 */
function MyPromise(fun){
    //用於生成MyPromise的id,其實在then執行的時候,都是利用同一個MyPromise將回調保存在events
    this.id = ++MyPromise.prototype.counts;
    var that = this;
    var resolve = function(value){
        var events = MyPromise.prototype.events;
        if(events.length>0){
            console.log("call resolve Promise"+that.id);
            var func = events.shift().res;//取出events隊列頭中的回調
            //異步執行,實際上是生成了新的MyPromise
            setTimeout(function(){func(value)},0);
        }
    };
    var reject = function(value){
        var events = MyPromise.prototype.events;
        if(events.length>0){
            console.log("call reject Promise"+that.id);
            var func = events.shift().rej;//取出events隊列頭中的回調
            //異步執行,實際上是生成了新的MyPromise
            setTimeout(function(){func(value)},0);
        }
    };
    //立即執行
    fun(resolve,reject);

}


MyPromise.prototype.counts = 0;
MyPromise.prototype.events = [];//回調隊列
/**
 * then方法用於保存回調
 * @param res
 * @param rej
 * @returns {MyPromise}
 */
MyPromise.prototype.then = function(res, rej){
    var events = MyPromise.prototype.events;
    //默認的狀態處理,所以可以不斷的調用.then並生成新的MyPromise
    var _res = function(value){return new MyPromise(function(res,rej){res(value)});};
    var _rej = function(value){return new MyPromise(function(res,rej){rej(value)});};
    if(res){
        _res = function(value){
            var result = res(value);
            if(result instanceof MyPromise)return result;
            return new MyPromise(function(res,rej){res(value)});
        };
    }
    if(rej){
        _rej = function(value){
            var result = rej(value);
            if(result instanceof MyPromise)return result;
            return new MyPromise(function(res,rej){rej(value)});
        };
    }

    events.push({res:_res,rej:_rej});
    console.log("call .then, Events Counts"+events.length);
    return this;
};

var getJSON = function(json){
    return new MyPromise(function(resolve,reject){
        setTimeout(function(){
            if(json=="6"){
            reject(("error from 3"));
        }else{
            resolve(json);
        }
    },1000);
    });
};
getJSON("1")
    .then(function(json){
        console.log(json);
    })
    .then(function(json){
        console.log(json);
    })
    .then(function(json){
        console.log(json);
        return getJSON("2");
    })
    .then(function(json){
        console.log(json);
    })
    .then(null,function(json){//如果不能正確處理狀態,會跳過
        console.log(json);
    })
    .then(function(json){
        console.log(json);
        return getJSON("6");
    })
    .then(function(json){
        console.log(json);
    })
    .then(null,function(json){
        console.log(json);
    })
    .then(function(json){
        console.log(json);
    })
    .then(null,function(json){
        console.log(json);
    });


輸出:

call .then, Events Counts1
call .then, Events Counts2
call .then, Events Counts3
call .then, Events Counts4
call .then, Events Counts5
call .then, Events Counts6
call .then, Events Counts7
call .then, Events Counts8
call .then, Events Counts9
call .then, Events Counts10
call resolve Promise1
1
call resolve Promise2
1
call resolve Promise3
1
call resolve Promise4
2
call resolve Promise5
call resolve Promise6
2
call reject Promise7
call reject Promise8
error from 3
call reject Promise9
call reject Promise10
error from 3

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章