class MyPromise {
static PENDING = 'pending'
static FULFILLED = 'fulfilled'
static REJECTED = 'rejected'
constructor(execute) {
this.status = MyPromise.PENDING
this.value = null
this.callbacks = []
try {
execute(this.resolve, this.reject)
} catch (err) {
this.reject(err)
}
}
resolve(value) {
if(this.status === MyPromise.PENDING) {
this.value = value
this.status = MyPromise.FULFILLED
setTimeout(() => {
this.callbacks.forEach(item => {
item.onFulfilled(this.value)
})
})
}
}
reject(err) {
if(this.status === MyPromise.PENDING) {
this.value = err
this.status = MyPromise.REJECTED
setTimeout(() => {
this.callbacks.forEach(item => {
item.onRejected(this.value)
})
})
}
}
then(onFulfilled, onRejected) {
if(typeof onFulfilled !== 'function') {
onFulfilled = (val) => val
}
if(typeof onRejected !== 'function') {
onRejected = (err) => err
}
let promise = new MyPromise((resolve, reject) => {
if(this.status === MyPromise.PENDING) {
this.callbacks.push({
onFulfilled: (value) => {
this.parse(promise, onFulfilled(value), resolve, reject)
},
onRejected: (err) => {
this.parse(promise, onRejected(err), resolve, reject)
}
})
} else if(this.status === MyPromise.FULFILLED) {
setTimeout(() => {
this.parse(promise, onFulfilled(this.value), resolve, reject)
})
} else {
setTimeout(() => {
this.parse(promise, onRejected(this.value), resolve, reject)
})
}
})
return promise
}
parse(promise, result, resolve, reject) {
if(promise === result) throw new Error("circular promise")
try {
if(result instanceof MyPromise) {
result.then(resolve, reject)
} else {
resolve(result)
}
} catch (err) {
reject(err)
}
}
static resolve(value) {
return new MyPromise((resolve, reject) => {
if(value instanceof MyPromise) {
value.then(resolve, reject)
} else {
resolve(value)
}
})
}
static reject(err) {
return new MyPromise((resolve, reject) => {
reject(err)
})
}
static all(promises) {
return new MyPromise((resolve, reject) => {
const result = []
let cnt = 0
const processData = (i, data, resolve) => {
result[i] = data
cnt ++
if(cnt === promises.length) {
resolve(result)
}
}
for(let i = 0; i < promises.length; i ++) {
promises[i].then((res) => {
processData(i, res, resolve)
}, (err) => {
reject(err)
})
}
})
}
static race(promises) {
return new MyPromise((resolve, reject) => {
for(let p of promises) {
p.then(resolve, reject)
}
})
}
catch(onRejected) {
return this.then(null, onRejected)
}
}
let p = new Promise((resolve) => {
resolve(true)
})
p.then((res) => {
return new Promise((resolve) => {
setTimeout(() => {
resolve("success")
}, 1000)
})
}).then((res) => {
console.log(res)
})