ES6
使用Typescript
实现Promise
const PENDING = 'PENDING'
const FULFILLED = 'FULFILLED'
const REJECTED = 'REJECTED'
type Executor = (resolve?: (data: unknown) => void, reject?: (reason: unknown) => void) => any
type OnRejected = (error?: any) => any
type OnFulfilled = (data?: any) => any
type Resolve = (data?: unknown) => any
type Reject = (data?: unknown) => any
class MyPromise {
#state: string
#result: unknown
#handlers: any[]
constructor(executor: Executor) {
this.#state = PENDING
this.#handlers = []
const resolve: Resolve = (data: unknown) => {
this.#changeState(FULFILLED, data);
}
const reject: Reject = (reason: unknown) => {
this.#changeState(REJECTED, reason)
}
try {
executor(resolve, reject)
} catch (err) {
reject(err)
}
}
#changeState(state: string, reason: unknown) {
if (this.#state !== PENDING) return
this.#state = state
this.#result = reason
this.#run()
}
#isPromiseLike(value: any) {
if (value !== null && (typeof value === 'object' || typeof value === 'function')) {
return typeof value.then === 'function'
}
return false
}
#runMicoTask(func: MutationCallback) {
if (typeof process === 'object' && typeof process.nextTick === 'function') {
process.nextTick(func)
} else if (typeof MutationObserver === 'function') {
const ob = new MutationObserver(func)
const textNode = document.createTextNode('1')
ob.observe(textNode, {
characterData: true
})
textNode.data = '2'
} else {
setTimeout(func, 0);
}
}
#runOne(callback: any, resolve: any, reject: any) {
queueMicrotask(() => {
if (typeof callback !== 'function') {
const settled = this.#state === FULFILLED ? resolve : reject
settled(this.#result)
return
}
try {
const data = callback(this.#result)
if (this.#isPromiseLike(data)) {
data.then(resolve, reject)
} else {
resolve(data)
}
} catch (error) {
reject(error)
}
})
}
#run() {
if (this.#state === PENDING) return
while (this.#handlers.length) {
const { onFulfilled, onRejected, resolve, reject } = this.#handlers.shift()
if (this.#state === FULFILLED) {
this.#runOne(onFulfilled, resolve, reject)
} else {
this.#runOne(onRejected, resolve, reject)
}
}
}
then(onFulfilled?: OnFulfilled, onRejected?: OnRejected) {
return new MyPromise((resolve, reject) => {
this.#handlers.push({
onFulfilled,
onRejected,
resolve,
reject
})
this.#run()
})
}
catch(onRejected: OnRejected) {
return this.then(undefined, onRejected)
}
finally(onFinlly: Function) {
return this.then(data => {
onFinlly()
return data
}, err => {
onFinlly()
throw err
})
}
static resolve(value: any) {
if (value instanceof MyPromise) return value
let _resolve: Resolve, _reject: Reject
const p = new MyPromise((resolve, reject) => {
_reject = reject
_resolve = resolve
})
if (p.#isPromiseLike(value)) {
value.then(_resolve, _reject)
} else {
_resolve(value)
}
return p
}
static reject(reason: any) {
return new MyPromise((resolve, reject) => {
reject(reason)
})
}
static all(promises: any[]) {
return new MyPromise((resolve, reject) => {
let results = [];
let counter = 0;
// 为数组中的每个promise添加回调
promises.forEach((promise, index) => {
Promise.resolve(promise).then(result => {
results[index] = result;
// 当所有promise都解决时,解决自定义的Promise
if (++counter === promises.length) {
resolve(results);
}
}).catch(reject); // 如果任何promise失败,则立即停止并失败
});
});
}
static any(promises: any[]) {
if (!Array.isArray(promises)) {
throw new TypeError('Promises must be an array');
}
return new MyPromise((resolve, reject) => {
let resolved = false;
const errors: any[] = [];
promises.forEach((promise) => {
if (resolved) return;
Promise.resolve(promise)
.then(resolve)
.catch((error) => {
errors.push(error);
if (errors.length === promises.length) {
reject(errors);
}
});
});
});
}
static rice(promises: any[]) {
if (!Array.isArray(promises)) {
throw new TypeError('promises must be an array');
}
return new MyPromise((resolve, reject) => {
let resolved = false;
const errors: any[] = [];
promises.forEach((promise) => {
if (resolved) return;
Promise.resolve(promise)
.then(resolve)
.catch((error) => {
reject(errors);
});
});
});
}
}