Promise手写

Promise A+ 规范

const PENDING = "pending"
const FULFILLED = "fulfilled"
const REJECTED = "rejected"

function enterMicroQueue(callack) {
    if (typeof callack !== "function") return
    if (typeof MutationObserver !== "undefined") {
        const div = document.createElement("div")
        const observer = new MutationObserver(callack)
        observer.observe(div, { childList: true })
        div.innerHTML = "1"
    } else if (process && process.nextTick) {
        process.nextTick(callack)
    } else {
        setTimeout(callack, 0)
    }
}

function isPromise(obj) {
    return !!(obj && typeof obj === "object" && typeof obj.then === "function")
}

class MyPromise {
    #handlers = []
    /**
     * 创建一个Promise
     * @param {Function} executor 任务执行器,立即执行
     */
    constructor(executor) {
        this._state = PENDING
        this._value = undefined
        try {
            if (typeof executor === "function") {
                executor(this.#resolve.bind(this), this.#reject.bind(this))
            }
        } catch (error) {
            this.#changeState(REJECTED, error)
        }
    }

    /**
     * 更改任务状态
     * @param {String} newState 新状态
     * @param {any} value 相关数据
     */
    #changeState(newState, value) {
        if (this._state !== PENDING) return
        if (isPromise(value)) {
            value.then(this.#resolve.bind(this), this.#reject.bind(this))
            return
        }
        Object.defineProperties(this, {
            _state: {
                configurable: false,
                enumerable: true,
                value: newState,
                writable: false,
            },
            _value: {
                configurable: false,
                enumerable: true,
                value: value,
                writable: false,
            },
        })
        // 状态落定后,执行 handlers
        this.#runHandlers()
    }

    /**
     * Promise A+规范的then
     * @param {Function} onFulfilled
     * @param {Function} onRejected
     */
    then(onFulfilled, onRejected) {
        return new MyPromise((resolve, reject) => {
            // 先收集 handlers
            this.#collectHandlers(onFulfilled, FULFILLED, resolve, reject)
            this.#collectHandlers(onRejected, REJECTED, resolve, reject)
            // 如果调用 then 方法前状态就确定了也执行 handlers
            this.#runHandlers()
        })
    }

    /**
     * 向处理队列中添加一个函数
     * @param {Function} executor 添加的函数
     * @param {String} state 该函数什么状态下执行
     * @param {Function} resolve 让then函数返回的Promise成功
     * @param {Function} reject 让then函数返回的Promise失败
     */
    #collectHandlers(executor, state, resolve, reject) {
        this.#handlers.push({
            executor,
            state,
            resolve,
            reject,
        })
    }

    /**
     * 根据实际情况,执行队列
     */
    #runHandlers() {
        if (this._state === PENDING) return
        while (this.#handlers[0]) {
            this.#runOneHandler(this.#handlers[0])
            this.#handlers.shift()
        }
    }

    /**
     * 处理一个handler
     * @param {Object} handler
     */
    #runOneHandler({ state, executor, resolve, reject }) {
        enterMicroQueue(() => {
            // 状态不一致,不处理
            if (this._state !== state) return
            // 传递后续处理并非一个函数
            if (typeof executor !== "function") {
                this._state === FULFILLED
                    ? resolve(this._value)
                    : reject(this._value)
                return
            }
            try {
                const result = executor(this._value)
                if (isPromise(result)) {
                    result.then(resolve, reject)
                } else {
                    resolve(result)
                }
            } catch (error) {
                reject(error)
            }
        })
    }

    /**
     * 标记当前任务完成
     * @param {any} data 任务完成的相关数据
     */
    #resolve(data) {
        this.#changeState(FULFILLED, data)
    }

    /**
     * 标记当前任务失败
     * @param {any} reason 任务失败的相关数据
     */
    #reject(reason) {
        this.#changeState(REJECTED, reason)
    }
}

catch()

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

finally()

/**
 * 状态敲定后,无论什么状态都要执行
 * @param {Function} onSettled 
 * @returns 返回新的 promise 与当前状态一样,如果 onSettled 报错,则返回拒绝的 promise
 */
finally(onSettled){
    return this.then((data) => {
        onSettled()
        return data
    }, (error) => {
        onSettled()
        throw error; // 抛出错误才会调用新 promise 的 reject 方法          
    })
}

resolve()

/**
 * 返回一个已完成的 Promise
 * 特殊情况:
 * 1. 传递的 data 本身就是 Promise 对象,则直接返回该 Promise
 * 2. 传递的 data 是 PromiseLike(Promise A+),返回新的 Promise,状态和其保持一致即可
 * @param {any} data
 */
static resolve(data) {
    if (data instanceof MyPromise) return data
    return new MyPromise((resolve, reject) => {
        if (isPromise(data)) {
            data.then(resolve, reject)
        } else {
            resolve(data)
        }
    })
}

reject()

/**
 * 得到一个被拒绝的Promise
 * @param {any} reason
 */
static reject(reason) {
    return new MyPromise((resolve, reject) => {
        reject(reason)
    })
}

all()

/**
 * 得到一个新的 Promise
 * 该 Promise 的状态取决于 proms 的执行
 * proms 是一个迭代器,包含多个 Promise
 * 全部 Promise 成功,则返回的 Promise 成功,数据为所有 Promise 成功的数据,并且顺序是按照传入的顺序排列
 * 只要有一个 Promise 失败,则返回的 Promise 失败,原因是第一个失败的 Promise 的原因
 * @param {iterator} proms
 */
static all(proms) {
    return new MyPromise((resolve, reject) => {
        try {
            const resultData = []
            let count = 0
            let fulfilledCount = 0
            for (const p of proms) {
                let i = count
                count++
                MyPromise.resolve(p).then((data) => {
                    fulfilledCount++
                    resultData[i] = data // 不能用[count-1], 因为在执行此函数时,count已经是最终结果
                    if (fulfilledCount === count) resolve(resultData)
                }, reject)
            }
            if (!count) resolve(resultData)
        } catch (error) {
            reject(error)
        }
    })
}

allSettled()

/**
 * 等待所有的 Promise 有结果之后
 * 该方法返回的 Promise 完成
 * 并且按照顺序将所有结果汇总
 * @param {iterator} proms
 */
static allSettled(proms) {
    const ps = []
    for (const p of proms) {
        ps.push(
            MyPromise.resolve(p).then(
                // 只要函数执行不报错,返回的 promise 必定成功,值就是返回值
                (value) => ({
                    states: FULFILLED,
                    value,
                }),
                (reason) => ({
                    states: REJECTED,
                    reason,
                })
            )
        )
    }
    return MyPromise.all(ps)
}

rance()

/**
 * 返回的 Promise 与第一个有结果的一致
 * @param {iterator} proms
 */
static race(proms) {
    return new MyPromise((resolve, reject) => {
        for (const p of proms) {
            MyPromise.resolve(p).then(resolve, reject)
        }
    })
}

any()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值