Interview question: javascript implement promise A+ standard, pass promises-aplus-tests

Witch Elaina
2 min readAug 1, 2021
/**
* Promise A+ standard implementatio
* pass promises-aplus-tests
*/
var PENDING = "pending"
var FULFILLED = "fulfilled"
var REJECT = "rejected"
var id = 0module.exports = class Promise {
constructor(todo) {
this.id = id
// use id distinct diff promise when debug
id += 1
todo(this.resolve.bind(this), this.reject.bind(this))
}
used = false
status = PENDING
value = null
reason = null
onFulfilleds = []
onRejects = []
resolve(value) {
if (this.status == PENDING) {
if (this.onFulfilleds.length > 0) {
// console.log(`this.id:${this.id} resolve`);
}
this.status = FULFILLED
this.value = value
this.onFulfilleds.forEach((fn) => {
fn(value);
})
}
}
reject(reason) {
if (this.status == PENDING) {
this.status = REJECT
this.reason = reason
this.onRejects.forEach((fn) => {
fn(reason)
})
}
}
then(onFulfilled, onRejected) {
if (typeof onFulfilled != "function") {
onFulfilled = (value) => {
return value
}
}
if (typeof onRejected != "function") {
onRejected = (reason) => {
throw reason
}
}
var p2 = new Promise((resolve, reject) => {
var asyncAndCatch = (fn) => {
setTimeout(() => {
try {
var r = fn()
this.resolvePromise(p2, r, resolve, reject)
} catch (e) {
reject(e)
}
})
}
if (this.status == PENDING) {
// console.log(`this.id:${this.id} push`)
this.onFulfilleds.push((value) => {
asyncAndCatch(() => {
return onFulfilled(value)
})
});
this.onRejects.push((reaons) => {
asyncAndCatch(() => {
return onRejected(reaons)
})
});
} else {
if (this.status == FULFILLED) {
asyncAndCatch(() => {
return onFulfilled(this.value)
})
} else if (this.status == REJECT) {
asyncAndCatch(() => {
return onRejected(this.reason)
})
}
}
}
)
return p2
}
resolvePromise(p2, result, resolve, reject) {
if (p2 == result) {
throw new TypeError("Chain cycle")
}
if (result /* typeof null == "object", so `result &&` to make sure result has value*/
&& (typeof result == "object" || typeof result == "function")) {
var used
try {
var then = result.then;
if (typeof then == "function") {
then.call(result, (val) => {
if (used) return
used = true
this.resolvePromise(p2, val, resolve, reject)
}, (reason) => {
if (used) return
used = true
reject(reason)
})
} else {
if (used) {
return
}
used = true
resolve(result)
}
} catch (e) {
if (used) {
return
}
used = true
reject(e)
}
} else {
// console.log(`caller.id:${this.id}`)
resolve(result)
}
}
}

If you like my article, donate me a coffee and let me continue

Donate Donate backup

--

--