手写Promise

参考资料

Promises 介绍文档

Promises/A+ 规范

Promises 的一种实现方式

github 上 2.6k+ star 的一个 Promise 实现方式

手写 Promise

自己手动实现的简易版 Promise,便于理解 Promise 工作原理。以下实现版本,并未完全 compilant to Promises/A+ 规范,但对于用户理解 Promise 工作原理已有很大帮助。
myPromise.js

let PENDING = 'pending'
let FULFILLED = 'fulfilled'
let REJECTED = 'rejected'


class Promise {
    state
    value
    handlers = []
    constructor(executor) {
        this.state = PENDING
        try {
            executor(this.#resolve.bind(this), this.#reject.bind(this))
        } catch (err) {
            this.#reject(err)
        }
    }

    #resolve(data) {
        this.#changeState(FULFILLED, data)
    }
    #reject(err) {
        this.#changeState(REJECTED, err)
    }

    #changeState(newState, data) {
        // 状态只能改变一次
        if (this.state !== PENDING) return
        this.state = newState
        this.value = data

        // 检查一下是否有 then() 添加的 handler,如果有,就将这些 handler 包装成 task 放入 micro task queue
        this.#runHandlers()
    }

    then(onFulfilled, onRejected) {
        return new Promise((resolve, reject) => {
            this.handlers.push(new Handler(onFulfilled, onRejected, resolve, reject))
            this.#runHandlers()
        })
    }

    /**
     * 
     * 将所有 handler 放入 micro task queue,不会阻塞很长时间
     */
    #runHandlers() {
        if (this.state === PENDING) return
        while (this.handlers.length > 0) {
            const handler = this.handlers.shift()
            queueMicrotask(() => {
                const { onFulfilled, onRejected, resolve, reject } = handler
                const onHandler = (this.state === FULFILLED) ? onFulfilled : onRejected
                const resolveOrReject = (this.state === FULFILLED) ? resolve : reject
                if (onHandler) {
                    try {
                        const result = onHandler(this.value)
                        if (isPromise(result)) {
                            result.then(resolve, reject)
                        } else {
                            resolve(result)
                        }
                    } catch (ex) {
                        reject(ex)
                    }
                } else {
                    resolveOrReject(this.value)
                }
            })
        }
    }
}

/**
 * 
 * @param {*} value onFulfilled/onRejected 返回的值
 * @returns true: 是 Promise; false: 不是 Promise
 * @reference 参考 Promises/A+规范:https://promisesaplus.com/
 * @reference 1.1 “promise” is an object or function with a then method whose behavior conforms to this specification.
 */
function isPromise(value) {
    return ((typeof value === 'object' || typeof value === 'function') && typeof value.then === 'function')
}


class Handler {
    constructor(onFulfilled, onRejected, resolve, reject) {
        this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null;
        this.onRejected = typeof onRejected === 'function' ? onRejected : null;
        this.resolve = resolve;
        this.reject = reject;
    }
}

export default Promise;

测试运行

testPromise.js

const Promise = require('./myPromise.js')

let p = new Promise((resolve) => {
    setTimeout(() => {
        resolve(200)
        console.log('timeout, p:', p)
    }, 3000)
})
p.then((val) => {
    console.log('the very first then, value:', val)
})
p.then((val) => {
    console.log('first then, value:', val)
    return new Promise((res, rej) => {
        res(val + 1)
    })
}).then((val) => {
    console.log('second then, value:', val)
    return new Promise((res, rej) => {
        rej(val + 1)
    })
}).then(null, (val) => {
    console.log('third then, rejected, value:', val)
    throw (val + 1)
}).then(null, (val) => {
    console.log('forth then, rejected, value:', val)
    return val + 1
}).then((val) => {
    console.log('fifth then, value:', val)
})

执行结果

$ node testPromise.js 
timeout, p: Promise { state: 'fulfilled', value: 200, handlers: [] }
the very first then, value: 200
first then, value: 200
second then, value: 201
third then, rejected, value: 202
forth then, rejected, value: 203
fifth then, value: 204
posted @ 2024-02-17 15:33  HorseShoe2016  阅读(5)  评论(0编辑  收藏  举报