JS神器 Promise 兼容

code:

// 兼容 window.Promise
(function(){
    "use strict";
    var Promise, proto;
    if(window.Promise) return;
    Promise = window.Promise = function(resolver){
        var self=this, c;
        // check
        if(!(this instanceof Promise))
            throw new Error('undefined is not a promise');
        if(typeof resolver!=='function')
            throw new Error('Promise resolver '+resolver+' is not a function');
        // init
        c = this.__Promise = {
            status:0, data:null, next:[], catched:false,
            done: function(data){ emit(self,data); },
            fail: function(err){ emit(self,err,true); }
        };
        if(resolver===noop) return this;
        // exec
        try{ resolver(c.done, c.fail); }
        catch(err){ c.fail(err); }
        return this;
    };
    proto = Promise.prototype;
    function noop(){}
    function emit($pm, data, isFail) {
        var c=$pm.__Promise, n;
        if(c.status!==0) return;
        if(!isFail && (data instanceof Promise))
            return data.then(c.done, c.fail);
        n = c.status = isFail ? 2 : 1;
        c.data = data;
        for(var i=0,l=c.next.length; i<l; i++){
            exec(c.next[i][0], c.next[i][n], c.data, isFail);
        }
        if(!isFail || c.catched) return;
        setTimeout(function(){
            if(c.catched) return;
            throw '(in promise) '+data;
        });
    }
    function exec($pm, fn, data, isFail){
        if(typeof fn!=='function') emit($pm, data, isFail);
        try{ emit($pm, fn(data)); }
        catch(err){ emit($pm, err, true); }
    }
    Promise.all = function(arr){
        var $pm=new Promise(noop), len=1, rt=[];
        for(var i=0; i<arr.length; i++){
            if(arr[i] instanceof Promise){
                if(len<0) arr[i].__Promise.catched = true;
                else{
                    len++;
                    (function(){
                        var n = i;
                        arr[n].then(
                            function(data){ rt[n] = data; if(!--len) emit($pm,rt); },
                            function(err){ emit($pm,err,true); len = -1; }
                        );
                    })();
                }
            }
            else if(len>0) rt[i] = arr[i];
        }
        if(!--len) $pm.__Promise.done(rt);
        return $pm;
    };
    Promise.race = function(arr){
        var $pm=new Promise(noop), isRt;
        for(var i=0; i<arr.length; i++){
            if(arr[i] instanceof Promise){
                if(isRt) arr[i].__Promise.catched = true;
                else{
                    arr[i].then(
                        function(data){ isRt = true; emit($pm,data); },
                        function(err){ isRt = true; emit($pm,err,true); }
                    )
                }
            }
            else if(!isRt){
                isRt = true;
                emit($pm, arr[i]);
            }
        }
        return $pm;
    };
    Promise.resolve = function(data){
        var $pm = new Promise(noop);
        emit($pm, data);
        return $pm;
    };
    Promise.reject = function(err){
        var $pm = new Promise(noop);
        emit($pm, err, true);
        return $pm;
    };
    proto.then = function(done, fail){
        var $pm=new Promise(noop), c=this.__Promise, s=c.status;
        c.catched = true;
        if(s===0) c.next.push([$pm, done, fail]);
        else if(s===1) exec($pm, done, c.data);
        else exec($pm, fail, c.data, true);
        return $pm;
    };
    proto.catch = function(fail){
        var $pm=new Promise(noop), c=this.__Promise, s=c.status;
        c.catched = true;
        if(s===0) c.next.push([$pm, null, fail]);
        else if(s===1) emit($pm, c.data);
        else exec($pm, fail, c.data, true);
        return $pm;
    };
})();

与es6对比  [es6: Chrome 版本 60.0.3112.101(正式版本) (64 位)]

codeconsloe.logUncaught(es6)Uncaught(兼容)
Promise();
nullUncaught TypeError: undefined is not a promiseUncaught Error: undefined is not a promise
Promise(1);
nullUncaught TypeError: undefined is not a promiseUncaught Error: undefined is not a promise
new Promise();
nullUncaught TypeError: Promise resolver undefined is not a functionUncaught Error: Promise resolver undefined is not a function
new Promise(1);
nullUncaught TypeError: Promise resolver 1 is not a functionUncaught Error: Promise resolver 1 is not a function
new Promise(function(done){
    done(1);
}).then();
nullnullnull
new Promise(function(done){
    done(1);
}).then(2);
nullnullnull
new Promise(function(done){
    done(1);
}).catch();
nullnullnull
new Promise(function(done){
    done(1);
}).catch(2);
nullnullnull
new Promise(function(done,fail){
    fail({a:1})
});
nullUncaught (in promise) {a: 1}Uncaught (in promise) [object Object]
new Promise(function(done,fail){
    fail(1);
}).catch();
nullUncaught (in promise) 1Uncaught (in promise) 1
new Promise(function(done,fail){
    fail(1);
}).catch(2);
nullUncaught (in promise) 1Uncaught (in promise) 1
new Promise(function(done){
    done(1);
}).then(function(data){
    console.log(data);
});
1nullnull
new Promise(function(done,fail){
    fail(1);
}).catch(function(data){
    console.log(data);
});
1nullnull
new Promise(function(done,fail){
    done(1);
    fail(2);
}).then(function(data){
    console.log(data);
});
1nullnull
new Promise(function(done,fail){
    fail(2);
    done(1);
}).then(function(data){
    console.log(data);
});
nullUncaught (in promise) 2Uncaught (in promise) 2
new Promise(function(done){
    setTimeout(function(){
        done(1);
    });
}).then(function(data){
    return data+1;
}).then(function(data){
    console.log(data);
});
2nullnull
new Promise(function(done,fail){
    fail(1);
}).then(function(data){
    console.log('then:', data);
}).catch(function(data){
    console.log('catch:', data);
});
catch: 1nullnull
new Promise(function(done,fail){
    setTimeout(function() {
        fail(1);
    });
}).catch(function(data){
    return 2;
}).then(function(data){
    console.log('then:', data);
});
then: 2nullnull
new Promise(function(){
    throw 1;
}).catch(function(data){
    console.log(data);
});
1nullnull
new Promise(function(done,fail){
    fail(2);
    throw 1;
}).catch(function(data){
    console.log(data);
});
2nullnull
new Promise(function(done){
    done(1);
}).then(function(data){
    console.log('then:', data);
},function(data){
    console.log('catch:', data);
});
then: 1nullnull
new Promise(function(done,fail){
    fail(1);
}).then(function(data){
    console.log('then:', data);
},function(data){
    console.log('catch:', data);
});
catch: 1nullnull
new Promise(function(done){
    done(Promise.resolve(1));
}).then(function(data){
    console.log(data);
});
1nullnull
new Promise(function(done){
    done(Promise.reject(1));
}).catch(function(data){
    console.log(data);
});
1nullnull
new Promise(function(done){
    done(1);
}).then(function(data){
    return data+1;
},function(data){
    console.log('catch:', data);
}).then(function(data){
    console.log('then:', data);
});
then: 2nullnull
new Promise(function(done,fail){
    fail(1);
}).then(function(data){
    console.log('then:', data);
},function(data){
    return data+1;
}).then(function(data){
    console.log('then2:', data);
});
then2: 2nullnull
new Promise(function(done,fail){
    fail(1);
}).then(function(data){
    console.log('then:', data);
},function(data){
    return Promise.resolve(data+1);
}).then(function(data){
    console.log('then2:', data);
});
then2: 2nullnull
new Promise(function(done,fail){
    fail(1);
}).then(function(data){
    console.log('then:', data);
},function(data){
    return Promise.reject(data+1);
}).catch(function(data){
    console.log('catch:', data);
});
catch: 2nullnull
var p1 = new Promise(function(done){
    setTimeout(function(){
        done(1);
    },2000);
});
var p2 = new Promise(function(done){
    setTimeout(function(){
        done(2);
    });
});
Promise.all([0,p1,p2]).then(function(data){
    console.log(data);
});
[0, 1, 2]nullnull
var p1 = new Promise(function(done){
    setTimeout(function(){
        done(1);
    },2000);
});
var p2 = new Promise(function(done,fail){
    setTimeout(function(){
        fail(2);
    });
});
Promise.all([p1,p2]).catch(function(data){
    console.log(data);
});
2nullnull
var p1 = new Promise(function(done){
    setTimeout(function(){
        done(1);
    },2000);
});
var p2 = new Promise(function(done){
    setTimeout(function(){
        done(2);
    },1000);
});
Promise.race([0,p1,p2]).then(function(data){
    console.log('then:', data);
},function(data){
    console.log('catch:', data);
});
then: 0nullnull
var p1 = new Promise(function(done){
    setTimeout(function(){
        done(1);
    },2000);
});
var p2 = new Promise(function(done){
    setTimeout(function(){
        done(2);
    },1000);
});
Promise.race([p1,p2]).then(function(data){
    console.log('then:', data);
},function(data){
    console.log('catch:', data);
});
then: 2nullnull
var p1 = new Promise(function(done){
    setTimeout(function(){
        done(1);
    },2000);
});
var p2 = new Promise(function(done,fail){
    setTimeout(function(){
        fail(2);
    },1000);
});
Promise.race([p1,p2]).then(function(data){
    console.log('then:', data);
},function(data){
    console.log('catch:', data);
});
catch: 2nullnull
var p1 = new Promise(function(done,fail){
    setTimeout(function(){
        fail(1);
    },2000);
});
var p2 = new Promise(function(done){
    setTimeout(function(){
        done(2);
    },1000);
});
Promise.race([p1,p2]).then(function(data){
    console.log('then:', data);
},function(data){
    console.log('catch:', data);
});
then: 2nullnull

转载于:https://my.oschina.net/u/993563/blog/1517122

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值