Appearance
手写 Promise 核心
我们实现一个简单的Promise,来加强对 Promise 的理解
最终效果
js
class MyPromise {
static PENDING = 'pending'
static FULFILLED = 'fulfilled'
static REJECTED = 'rejected'
constructor(executor) {
this.status = MyPromise.PENDING
this.value = null
this.callbacks = []
try {
executor(this.resolve.bind(this), this.reject.bind(this))
}
catch (error) {
this.reject(error.message)
}
}
resolve(value) {
if (this.status === MyPromise.PENDING) {
this.status = MyPromise.FULFILLED
this.value = value
setTimeout(() => {
this.callbacks.forEach((callback) => {
callback.onFulfilled(value)
})
})
}
}
reject(reason) {
if (this.status === MyPromise.PENDING) {
this.status = MyPromise.REJECTED
this.value = reason
setTimeout(() => {
this.callbacks.forEach((callback) => {
callback.onRejected(reason)
})
})
}
}
then(onFulfilled, onRejected) {
if (typeof onFulfilled !== 'function')
onFulfilled = () => this.value
if (typeof onRejected !== 'function')
onRejected = () => this.value
const promise = new MyPromise((resolve, reject) => {
if (this.status === MyPromise.PENDING) {
this.callbacks.push({
onFulfilled: (value) => {
const result = onFulfilled(value)
this.parse(promise, result, resolve, reject)
},
onRejected: (reason) => {
const result = onRejected(reason)
this.parse(promise, result, resolve, reject)
},
})
}
if (this.status === MyPromise.FULFILLED) {
setTimeout(() => {
const result = onFulfilled(this.value)
this.parse(promise, result, resolve, reject)
})
}
if (this.status === MyPromise.REJECTED) {
setTimeout(() => {
const result = onRejected(this.value)
this.parse(promise, result, resolve, reject)
})
}
})
return promise
}
parse(promise, result, resolve, reject) {
if (promise == resolve)
throw new TypeError('Chaining cycle detected for promise #<MyPromise>')
try {
if (result instanceof MyPromise)
result.then(resolve, reject)
else
resolve(result)
}
catch (error) {
reject(error)
}
}
static resolve(value) {
return new MyPromise((resolve, reject) => {
if (value instanceof MyPromise)
value.then(resolve, reject)
else
resolve(value)
})
}
static reject(reason) {
return new MyPromise((resolve, reject) => {
reject(reason)
})
}
static all(promises) {
return new MyPromise((resolve, reject) => {
const result = []
let count = 0
for (let i = 0; i < promises.length; i++) {
promises[i].then(
(value) => {
result[i] = value
count++
if (count === promises.length)
resolve(result)
},
(reason) => {
reject(reason)
}
)
}
})
}
static race(promises) {
return new MyPromise((resolve, reject) => {
for (let i = 0; i < promises.length; i++) {
promises[i].then(
(value) => {
resolve(value)
},
(reason) => {
reject(reason)
}
)
}
})
}
}