Skip to content

Instantly share code, notes, and snippets.

@mutongwu
Created April 24, 2018 09:57
Show Gist options
  • Save mutongwu/79d25a8447b56f33ae35eb13d50d81ac to your computer and use it in GitHub Desktop.
Save mutongwu/79d25a8447b56f33ae35eb13d50d81ac to your computer and use it in GitHub Desktop.
a tiny promise polyfill
function isThenable(obj){
if(obj && typeof obj.then === 'function'){
return true;
}
return false;
}
function ChainedPromise(promise, rv, rj){
this.success = [rv];
this.fail = [rj];
this.promise = promise;
this.value = null;
}
ChainedPromise.prototype = {
then: function(rv, rj){
var data = this.promise.data;
if(data.state === 2){
if(data.flag){
rv(this.value);
}else{
rj(this.value);
}
}else{
if(rv){
this.success.push(rv);
}
if(rj){
this.fail.push(rj);
}
}
return this;
},
_do: function(val, isResolved){
var _this = this;
var jobs = isResolved ? this.success: this.fail;
this.value = val;
if(jobs.length){
val = (jobs.shift())(this.value);
if(isThenable(val)){
val.then(function(res){
_this.resolve(res);
});
return;
}
this.value = val;
}
setTimeout(function(){
while(jobs.length){
val = (jobs.shift())(_this.value);
if(isThenable(val)){
val.then(function(res){
_this.resolve(res);
});
break;
}
_this.value = val;
}
},0);
},
resolve: function(val){
this._do(val, true);
},
reject: function(val){
this._do(val, false);
}
};
function TinyPromise(fn){
var _this = this;
this.data = {
success:[],
fail:[],
state:0, // 0:未执行、1:执行中、2:执行完成
flag: null, // true:成功执行;false:失败执行
value:null,
chained:[] //链式对象
}
// this.chained = new ChainedPromise(this);
setTimeout(function(){
fn.call(_this,function(res){
_this._exec(res, true);
}, function(res){
_this._exec(res, false);
});
},0);
}
TinyPromise.prototype = {
then: function(rv, rj){
var data = this.data;
if(data.state === 2){
if(data.flag){
rv(data.value);
}else{
rj(data.value);
}
}
if(data.state === 0){
data.state = 1;
}
var chain = new ChainedPromise(this,rv, rj);
data.chained.push(chain);
return chain;
},
_exec: function (res, isResolved) {
var data = this.data;
var method = isResolved ? 'resolve': 'reject';
if(data.state !== 2){
data.value = res;
data.state = 2;
data.flag = !!isResolved;
while(data.chained.length){
(data.chained.shift())[method](res);
}
}
}
}
TinyPromise.resolve = function(value) {
if (value && isThenable(value)) {
return value;
}
return new TinyPromise(function(resolve) {
resolve(value);
});
};
TinyPromise.reject = function(value) {
return new TinyPromise(function(resolve, reject) {
reject(value);
});
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment