Last active
August 29, 2015 14:25
-
-
Save linktohack/d7184a0317d43f0f9c40 to your computer and use it in GitHub Desktop.
Promise in 50 lines of code
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var Promise = (function() { | |
var Promise = function(callback) { | |
this._done = []; | |
this._fail = []; | |
this.state = 'pending'; | |
this.value = undefined; | |
callback && callback(this.resolve.bind(this), this.reject.bind(this)); | |
}; | |
Promise.prototype = { | |
resolve: function(value) { | |
this.state = 'resolved'; | |
this.value = value; | |
this._done.forEach(function(each) { | |
window.setTimeout(function() { | |
thenValue = each.callback(value); | |
if (thenValue && typeof thenValue.state === 'resolved') { | |
each.promise.resolve(thenValue.value) | |
} | |
else if (thenValue && typeof thenValue.state === 'rejected') { | |
each.promise.rejected(thenValue.value) | |
} | |
else if (thenValue && typeof thenValue.then === 'function') { | |
thenValue.then(each.promise.resolve.bind(each.promise), | |
each.promise.reject.bind(each.promise)); | |
} else { | |
each.promise.resolve(thenValue); | |
} | |
}); | |
}); | |
return this; | |
}, | |
reject: function(reason) { | |
this.state = 'rejected'; | |
this.value = reason; | |
this._fail.forEach(function(each) { | |
window.setTimeout(function() { | |
thenValue = each.callback(reason); | |
if (thenValue && typeof thenValue.state === 'resolved') { | |
each.promise.resolve(thenValue.value) | |
} | |
else if (thenValue && typeof thenValue.state === 'rejected') { | |
each.promise.rejected(thenValue.value) | |
} | |
else if (thenValue && typeof thenValue.then === 'function') { | |
thenValue.then(each.promise.resolve.bind(each.promise), | |
each.promise.reject.bind(each.promise)); | |
} else { | |
each.promise.reject(thenValue); | |
} | |
}); | |
}); | |
return this; | |
}, | |
then: function(done, fail) { | |
var newPromise = new Promise(); | |
switch (this.state) { | |
case 'pending': | |
done && this._done.push({ callback: done, promise: newPromise }); | |
fail && this._fail.push({ callback: fail, promise: newPromise }); | |
break; | |
case 'resolved': | |
newPromise.then(done, fail); | |
newPromise.resolve(this.value); | |
break; | |
case 'rejected': | |
newPromise.then(done, fail); | |
newPromise.reject(this.value); | |
} | |
return newPromise; | |
}, | |
}; | |
Promise.all = function(promises, values) { | |
promises = promises || []; | |
values = values || []; | |
var newPromise = new Promise(); | |
var first = promises.pop(); | |
if (first === undefined ) { | |
newPromise.resolve(values); | |
} else { | |
first.then(function(value) { | |
values.unshift(value); | |
Promise.all(promises, values).then(newPromise.resolve.bind(newPromise)); | |
}, function(reason) { | |
newPromise.reject(reason); | |
}); | |
} | |
return newPromise; | |
} | |
return Promise; | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment