MyPromise.resolve = function (x) {
return (x instanceof MyPromise) ? x : (new MyPromise((resolve) => resolve(x)))
}
MyPromise.reject = function (r) {
return new MyPromise((undefined, reject) => { reject(r) })
}
const isIterable = function (x) {
if (x !== undefined && x !== null && typeof x[Symbol.iterator] === 'function') {
return true
} else {
throw new TypeError(`${typeof x} ${x} is not iterable (cannot read property Symbol(Symbol.iterator))`)
}
}
rejected: TypeError: undefined is not iterable (cannot read property Symbol(Symbol.iterator))
rejected: TypeError: object null is not iterable (cannot read property Symbol(Symbol.iterator))
rejected: TypeError: boolean true is not iterable (cannot read property Symbol(Symbol.iterator))
rejected: TypeError: boolean false is not iterable (cannot read property Symbol(Symbol.iterator))
rejected: TypeError: number 5 is not iterable (cannot read property Symbol(Symbol.iterator))
rejected: TypeError: object is not iterable (cannot read property Symbol(Symbol.iterator))
MyPromise.race = function (promises) {
return new MyPromise((resolve, reject) => {
// must be iterable promises
if (isIterable(promises)) {
for (let p of promises) {
MyPromise.resolve(p).then(resolve, reject)
}
}
})
}
MyPromise.all = function (promises) {
return new MyPromise((resolve, reject) => {
// must be iterable promises
if (isIterable(promises)) {
const len = promises.length
// empty iterable
if (len === 0) {
resolve([])
}
// iterable
let result = new Array(len)
let count = 0
for (let i in promises) {
MyPromise.resolve(promises[i])
.then((value) => {
count++
result[i] = value
if (count === len) {
resolve(result)
}
}).catch(reject)
}
}
})
}
MyPromise.allSettled = function (promises) {
return new MyPromise((resolve, reject) => {
// must be iterable promises
if (isIterable(promises)) {
const len = promises.length
// empty iterable
if (len === 0) {
resolve([])
}
// iterable
let result = new Array(len)
let count = 0
for (let i in promises) {
MyPromise.resolve(promises[i])
.then((value) => {
result[i] = {
status: 'fulfilled',
value
}
})
.catch((reason) => {
result[i] = {
status: 'rejected',
reason
}
})
.finally(() => {
count++
if (count === len) {
resolve(result)
}
})
}
}
})
}
MyPromise.any = function (promises) {
return new MyPromise((resolve, reject) => {
// must be iterable promises
if (isIterable(promises)) {
const len = promises.length
// empty iterable
if (len === 0) {
throw new AggregateError([], 'empty promises')
}
// iterable
let errors = new Array(len)
let errorCount = 0
for (let i in promises) {
MyPromise.resolve(promises[i])
.then((value) => resolve(value))
.catch((reason) => {
errorCount++
errors[i] = reason
if (errorCount === len) {
reject(new AggregateError(errors, 'All promises were rejected'))
}
})
}
}
})
}