Promise

Constructor

Promise

  • 处理 state 的单向变化
  • 处理 then() 的同步回调
  • 处理 then() 的异步回调
  • 处理 then() 的链式调用
  • 处理 then() 的微任务
  • 处理 then() 的传值穿透
class MyPromise {
	constructor(executor) {
		this.state = 'pending'
		this.result = undefined
		this.onFulfilledCallbacks = []
		this.onRejectedCallbacks = []
		
		const resolve = () => {}
		const reject = () => {}
		
		executor(resolve, reject)
	}
	
	then() {}
	catch() {}
	finally() {}
	static all() {}
	static any() {}
	static allSettled() {}
	static race() {}
	static resolve() {}
	static reject() {}
}
constructor(executor) {
	this.state = 'pending'
	this.result = undefined
	this.onFulfilledCallbacks = []
	this.onRejectedCallbacks = []
	
	const resolve = value => {
		queueMicrotask(() => { // 处理微任务
			if (this.state === 'pending') { // 处理状态单次变化
				this.state = 'fulfilled'
				this.result = value
				this.onFulfilledCallbacks.forEach(cb => cb(this.result))
			}
		})
	}
	
	const reject = value => {
		queueMicrotask(() => {
			if (this.state === 'pending') {
				this.state = 'rejected'
				this.result = value
				this.onRejectedCallbacks.forEach(cb => cb(this.result))
			}
		})
	}
 
  try {executor(resolve, reject)}
  catch(e) {reject(e)}
}

Instance methods

then

then(onFulfilled, onRejected) {
	onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : x => x // 处理传值穿透
	onRejected = typeof onRejected === 'function' ? onRejected : x => { throw x }
 
	return new MyPromise((resolve, reject) => { // 处理链式调用
		const resolvePromise = result => {
			if (result instanceof MyPromise) {result.then(resolve, reject)}
			else {resolve(result)}
		}
 
		if (this.state === 'fulfilled') {resolvePromise(onFulfilled(this.result))} // 处理同步回调
		if (this.state === 'rejected') {resolvePromise(onRejected(this.result))}
		if (this.state === 'pending') {
			this.onFulfilledCallbacks.push(value => resolvePromise(onFulfilled(value))) // 处理异步回调
			this.onRejectedCallbacks.push(value => resolvePromise(onRejected(value)))
		}
	})
}

catch

catch(onRejected) {
	return this.then(undefined, onRejected)
}

finally

finally(onFinally) {
	const onFulfilled = value => {
		onFinally()
		return value
	}
	return this.then(onFulfilled, onFulfilled)
}

Static Methods

all

function all(promises) {
    return new Promise((resolve, reject) => {
        let result = []
        const onFullfiled = val => {
            result.push(val)
            if (result.length === promises.length) resolve(result)
        }
        const onRejected = val => {
            reject(val)
        }
        for (let promise of promises) {
            if (promise instanceof Promise) {
                promise.then(onFullfiled, onRejected)
            } else {
                onFullfiled(promise)
            }
        }
    })
}
 
Promise.all = all

race

function race(promises) {
    return new Promise((resolve, reject) => {
        for (let promise of promises) {
            if (promise instanceof Promise) {
                promise.then(resolve, reject)
            } else {
                resolve(promise)
            }
        }
    })
}
 
Promise.race = race

any

static any(promises) {
	return new MyPromise((resolve, reject) => {
		let result = []
		
		const onFulfilled = value => {resolve(value)}
		
		const onRejected = value => {
			result.push(value)
			if (result.length === promises.length) {reject(new AggregateError('All promises were rejected'))}
		}
		
		promises.forEach(promise => {
			if (promise instanceof MyPromise) {promise.then(onFulfilled, onRejected)}
			else {onFulfilled(promise)}
		})
	})
}

allSettled

static allSettled(promises) {
	return new MyPromise((resolve, reject) => {
		let result = []
		
		const onFulfilled = value => {
			result.push({ state: 'fulfilled', result: value })
			if (result.length === promises.length) {resolve(result)}
		}
		
		const onRejected = value => {
			result.push({ state: 'rejected', result: value })
			if (result.length === promises.length) {resolve(result)}
		}
		
		promises.forEach(promise => {
			if (promise instanceof MyPromise) {promise.then(onFulfilled, onRejected)}
			else {onFulfilled(promise)}
		})
	})
}

resolve

static resolve(value) {
	return new MyPromise((resolve, reject) => {
		if (value instanceof MyPromise) {value.then(resolve, reject)}
		else {resolve(value)}
	})
}

reject

static reject(value) {
	return new MyPromise((resolve, reject) => {
		reject(value)
	})
}