Skip to content

Instantly share code, notes, and snippets.

@wavded
Last active May 6, 2021 13:25
Show Gist options
  • Star 28 You must be signed in to star a gist
  • Fork 7 You must be signed in to fork a gist
  • Save wavded/5692344 to your computer and use it in GitHub Desktop.
Save wavded/5692344 to your computer and use it in GitHub Desktop.
Promise A+ Implementation
"use strict"
var Promise = function () {
this.state = 'pending'
this.thenables = []
}
Promise.prototype.resolve = function (value) {
if (this.state != 'pending') return
this.state = 'fulfilled'
this.value = value
this._handleThen()
return this
}
Promise.prototype.reject = function (reason) {
if (this.state != 'pending') return
this.state = 'rejected'
this.reason = reason
this._handleThen()
return this
}
Promise.prototype._handleThen = function () {
if (this.state == 'pending') return
if (this.thenables.length) {
for (var i = 0; i < this.thenables.length; i++) {
var thenPromise = this.thenables[i].promise
var returnedVal
try {
switch (this.state) {
case 'fulfilled':
if (this.thenables[i].fulfill) {
returnedVal = this.thenables[i].fulfill(this.value)
} else {
thenPromise.resolve(this.value)
}
break
case 'rejected':
if (this.thenables[i].reject) {
returnedVal = this.thenables[i].reject(this.reason)
} else {
thenPromise.reject(this.reason)
}
break
}
if (returnedVal == null) { // ???
this.thenables[i].promise.resolve(returnedVal)
}
else if (returnedVal instanceof Promise || typeof returnedVal.then == 'function') {
returnedVal.then(thenPromise.resolve.bind(thenPromise), thenPromise.reject.bind(thenPromise))
}
else {
this.thenables[i].promise.resolve(returnedVal)
}
} catch (e) {
thenPromise.reject(e)
}
}
this.thenables = []
}
}
Promise.prototype.then = function (onFulfilled, onRejected) {
var thenable = {}
if (typeof onFulfilled == 'function') {
thenable.fulfill = onFulfilled
}
if (typeof onRejected == 'function') {
thenable.reject = onRejected
}
if (this.state != 'pending') {
setImmediate(function () {
this._handleThen()
}.bind(this))
}
thenable.promise = new Promise()
this.thenables.push(thenable)
return thenable.promise
}
module.exports = Promise
"use strict"
var promisesTest = require('promises-aplus-tests')
var Promise = require('./promise')
var adapter = {
fulfilled: function (value) {
var promise = new Promise()
return promise.resolve(value)
},
rejected: function (reason) {
var promise = new Promise()
return promise.reject(reason)
},
pending: function () {
var promise = new Promise()
return {
promise: promise,
fulfill: promise.resolve.bind(promise),
reject: promise.reject.bind(promise)
}
}
}
promisesTest(adapter, function (er) {
if (er) console.error(er)
process.exit()
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment