MyPromise
class MyPromise {
constructor(executor) {
this.state = "pending"
this.value = null
this.reason = undefined
this.onResolvedCallbacks = []
this.onRejectCallbacks = []
let resolve = (value) => {
if (this.state === "pending") {
this.state = "fulfilled"
this.value = value
this.onResolvedCallbacks.forEach((fn) => fn())
}
}
let reject = (reason) => {
if (this.state === "pending") {
this.state = "rejected"
this.reason = reason
this.onRejectCallbacks.forEach((fn) => fn())
}
}
try {
executor(resolve, reject)
} catch (err) {
reject(err)
}
}
then(onFulfilled, onRejected) {
onFulfilled =
typeof onFulfilled === "function" ? onFulfilled : (value) => value
onRejected =
typeof onRejected === "function"
? onRejected
: (err) => {
throw err
}
let promise2 = new MyPromise((resolve, reject) => {
if (this.state === "fulfilled") {
setTimeout(() => {
try {
let x = onFulfilled(this.value)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
})
}
if (this.state === "rejected") {
setTimeout(() => {
try {
let x = onRejected(this.reason)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
})
}
if (this.state === "pending") {
this.onResolvedCallbacks.push(() => {
setTimeout(() => {
try {
let x = onFulfilled(this.value)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
})
})
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
let x = onRejected(this.reason)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
})
})
}
})
return promise2
}
catch = function (fn) {
return this.then(null, fn)
}
static all (promises) {
const values = []
return new MyPromise((resolve, reject) => {
promises.forEach((promise) => {
promise.then(
(value) => {
values.push(value)
if (values.length === promises.length) resolve(values)
},
(reason) => {
reject(reason)
}
)
})
})
}
static race (promises) {
return new MyPromise((resolve, reject) => {
promises.map((promise) => {
promise.then(
(value) => resolve(value),
(reason) => reject(reason)
)
})
})
}
static resolve (val) {
return new MyPromise((resolve, reject) => {
reject(val)
})
}
static reject (val) {
return new MyPromise((resolve, reject) => {
reject(val)
})
}
}
function resolvePromise(promise2, x, resolve, reject) {
if (x === promise2) {
return reject(new TypeError("chaining cycl detected for promise"))
}
let called
if (x != null && (typeof x === "object" || typeof x === "function")) {
try {
let then = x.then
if (typeof then === "function") {
then.call(
x,
(y) => {
if (called) return
called = true
resolvePromise(x, y, resolve, reject)
},
(err) => {
if (called) return
called = true
reject(err)
}
)
} else {
resolve(x)
}
} catch (e) {
if (called) return
called = true
reject(e)
}
} else {
resolve(x)
}
}