您的位置:首页 > Web前端 > JavaScript

JS神器 Promise 兼容

2017-08-19 00:00 246 查看
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]
, 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
.then(
function(data){ rt
= 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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Promise