function Promise(executor) {
const self = this;
self.promiseState = 'pending'
self.promiseResult = undefined;
self.callbacks = [];
function resolve(value) {
if (self.promiseState !== 'pending') return;
self.promiseState = 'fulfilled'
self.promiseResult = value
self.callbacks.forEach(callback => {
queueMicrotask(() => {
callback.onResolved(value)
})
})
}
function reject(reason) {
if (self.promiseState !== 'pending') return
self.promiseState = 'rejected'
self.promiseResult = reason
self.callbacks.forEach(callback => {
queueMicrotask(() => {
callback.onRejected(reason)
})
})
}
try {
executor(resolve, reject)
} catch(e) {
reject(e)
}
}
Promise.prototype.then = function(onResolved, onRejected) {
const self = this
if (typeof onResolved !== 'function') {
onResolved = value => value
}
onResolved = typeof onResolved == 'function' ? onResolved : value => value;
onRejected = typeof onRejected == 'function' ? onRejected : reason => {
throw reason;
}
const newPromise = new Promise((resolve, reject) => {
const fun = (callback) {
queueMicrotask(() => {
try {
const result = callback(self.promiseResult)
if (result == newPromise) {
reject(new TypeError('Chaining cycle detected'))
return;
}
if (result instanceof Promise) {
result.then(v => {
resolve(v)
}, r => {
reject(r)
})
} else {
resolve(result)
}
} catch(e) {
reject(e)
}
})
}
if (this.promiseState === 'fulfilled') {
fun(onResolved)
}
if (this.promiseState === 'rejected') {
fun(onRejected)
}
if (this.promiseState === 'pending') {
this.callbacks.push({
onResolved() {
fun(onResolved)
},
onRejected() {
fun(onRejected)
}
})
}
})
return newPromise;
}
Promise.prototype.catch = function(onRejected) {
return this.then(null, onRejected)
}
Promise.prototype.finally = function(onFinally) {
return new Promise((resolve, reject) => {
queueMicrotask(() => {
const result = onFinally()
if (result instanceof Promise) {
result.then(resolve, reject)
} else {
resolve(result)
}
})
})
}
Promise.resolve = function(value) {
return new Promise((resolve, reject) => {
if (value instanceof Promise) {
value.then(resolve, reject)
} else if (value && typeof value.then == 'function') {
value.then(resolve, reject)
} else {
resolve(value)
}
})
}
Promise.reject = function(reason) {
return new Promise((resolve, reject) => {
return reject(reason)
})
}
Promise.all = function(promises) {
var result = new Array(promises)
var count = 0
if (promises.length == 0) {
return [];
}
return new Promise((resolve, reject) => {
promises.forEach((promise, i) => {
if (promise instanceof Promise) {
promise.then(v => {
result[i] = v
if (++count == promises.length) {
resolve(result)
}
}, reject)
} else {
result[i] = promise
}
})
})
}
Promise.race = function(promises) {
return new Promise((resolve, reject) => {
promises.forEach(promise => {
if (promise instanceof Promise) {
promise.then(resolve, reject)
} else {
resolve(promise)
}
})
})
}
Promise.allSettled = function(promises) {
const result = []
const result_ = []
return new Promise((resolve, reject) => {
promises.forEach((promise, i) => {
if (promise instanceof Promise) {
promise.then(v => {
result[i] = {
status: 'fulfilled',
value: v
}
result_.push(v)
if (result_.length === promises.length) {
resolve(result)
}
}, r => {
result[i] = {
status: 'rejected',
value: r
}
result_.push(r)
if (result_.length === promises.length) {
resolve(result)
}
})
} else {
result[i] = {
status: 'fulfilled',
value: promise
}
result_.push(promise)
if (result_.length === promises.length) {
resolve(result)
}
}
})
})
}
Promise.any = function(promises) {
const result = []
const result_ = []
return new Promise((resolve, reject) => {
promises.forEach((promise, i) => {
if (promise instanceof Promise) {
promise.then(v => {
resolve(v)
}, r => {
result[i] = r
result_.push(r)
if (result_.length === promises.length) {
const error = new AggregateError(result, 'All promises were rejected')
reject(error)
}
})
} else {
resolve(promise)
}
})
})
}