学习JS高级练习一篇
const PROMISE_STATUS_PENDING = 'pending'
const PROMISE_STATUS_FULFILLED = 'fulfilled'
const PROMISE_STATUS_REJECTED = 'rejected'
class XYPromise {
constructor(executor) {
this.status = PROMISE_STATUS_PENDING
this.value = undefined
this.reason = undefined
this.onfulfilledfns = []
this.onrejectfns = []
const resolve = (value) => {
queueMicrotask(() => {
if(this.status !== PROMISE_STATUS_PENDING) return
this.status = PROMISE_STATUS_FULFILLED
this.value = value
this.onfulfilledfns.forEach((fn) => {
fn(this.value)
})
})
}
const reject = (value) => {
queueMicrotask(() => {
if(this.status !== PROMISE_STATUS_PENDING) return
this.status = PROMISE_STATUS_REJECTED
this.reason = value
this.onrejectfns.forEach((fn) => {
fn(this.reason)
})
})
}
try {
executor(resolve, reject)
} catch (err) {
reject(err)
}
}
then(onfulfilled, onrejected) {
return new XYPromise((resolve, reject) => {
const defaultOnfulfilled = (res) => {
return res
}
const defaultOnrejected = (err) => {
throw err
}
onfulfilled = onfulfilled || defaultOnfulfilled
onrejected = onrejected || defaultOnrejected
if (this.status === PROMISE_STATUS_FULFILLED) {
try {
const value = onfulfilled(this.value)
resolve(value)
} catch (err) {
reject(err)
}
}
if (this.status === PROMISE_STATUS_REJECTED) {
try {
const value = onrejected(this.reason)
resolve(value)
} catch (err) {
reject(err)
}
}
if (this.status === PROMISE_STATUS_PENDING) {
this.onfulfilledfns.push(() => {
try {
const value = onfulfilled(this.value)
resolve(value)
} catch (err) {
reject(err)
}
})
this.onrejectfns.push(() => {
try {
const value = onrejected(this.reason)
resolve(value)
} catch (err) {
reject(err)
}
})
}
})
}
catch(onrejected) {
return this.then(undefined, onrejected)
}
finally(onfinally) {
this.then(()=>{
onfinally()
}, () => {
onfinally()
})
}
static resolve (value) {
return new XYPromise(resolve => {
resolve(value)
})
}
static reject (value) {
return new XYPromise((resolve, reject) => {
reject(value)
})
}
static all (promises) {
return new XYPromise((resolve, reject) => {
const results = []
promises.forEach(p => {
p.then(res => {
results.push(res)
if(results.length === promises.length) {
resolve(results)
}
}, err => {
reject(err)
})
})
})
}
static allSettled (promises) {
return new XYPromise((resolve, reject) => {
const results = []
promises.forEach(p => {
p.then(res => {
results.push({
status: PROMISE_STATUS_FULFILLED,
value: res
})
if(results.length === promises.length) {
resolve(results)
}
}, err => {
results.push({
status: PROMISE_STATUS_REJECTED,
reason: err
})
if(results.length === promises.length) {
resolve(results)
}
})
})
})
}
static race (promises) {
return new XYPromise((resolve, reject) => {
promises.forEach(p =>{
p.then(res => {
resolve(res)
}, err => {
reject(err)
})
})
})
}
static any (promises) {
return new XYPromise((resolve, reject) => {
const errs = []
promises.forEach(p=> {
p.then(res =>{
resolve(res)
}, err => {
errs.push(err)
if(errs.length === promises.length) {
reject( new AggregateError(errs) )
}
})
})
})
}
}
const p1 = new XYPromise((resolve, reject) => {
setTimeout(()=>{
throw new Error('err!!!!')
}, 1000)
})
const p2 = new XYPromise((resolve, reject) => {
setTimeout(()=>{
reject('err msg2')
}, 2000)
})
const p3 = new XYPromise((resolve, reject) => {
setTimeout(()=>{
resolve('333')
reject('err msg3')
}, 3000)
})
const p = XYPromise.any([p1,p2,p3])
.then(res=>{
console.log('res1', res)
}).catch(err=>{
console.log('err1', err.errors)
}).finally(() =>{
console.log('finally')
})