如何手写一个promise函数

const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECT = 'rejected'; 

class MyPromise {

    #state = PENDING
    #result = undefined
    #handler = []

    constructor(executor){
        const resolve = (data) => {
            this.#changeState(FULFILLED, data)
        }
        const reject = (err) => {
            this.#changeState(REJECT, err)
        }

        try{
            executor(resolve, reject)
        }
        catch(err){
            reject(err)
        }
    }
    #changeState(state, result){
        if(this.#state !== PENDING) return
        this.#state = state
        this.#result = result

        this.#run()

    }
    // 判断这个callback是不是一个promise
    #isPromiseLike(value){
        return typeof value === 'object' && typeof value.then === 'function'
        // return value instanceof MyPromise || value[Symbol.for('nodejs.runtime.asm.promise')] instanceof MyPromise || value[Symbol.for('nodejs.runtime.asm.promise.constructor')] instanceof MyPromise;
    }
    // 手动将函数添加到微任务
    #runMicroTask(fun){
        if (typeof MutationObserver !== 'undefined') {
            const textNode = document.createTextNode('0')
            const ob = new MutationObserver(fun)
            ob.observe(textNode, { characterData: true })
            textNode.data = '1'
          } else {
            process.nextTick(fun)
          }
    }
    #runCall(callBack, resolve, reject){

        // then中的回调需要放在微队列中
        this.#runMicroTask(() => {
            // console.log('www',callBack, resolve, reject)
            if (typeof callBack === "function") {
                
                try{
                    const data = callBack(this.#result);
                    // 判断这个data返回的是不是一个promise
                   if(this.#isPromiseLike(data)){
                       
                       data.then(resolve, reject)
                       
                    } else resolve(data)
                }
                catch{
                    reject(this.#result)
                }
    
            } else {
                const settled = this.#state === FULFILLED ? resolve : reject
                settled(this.#result) //链式回调穿透
            }
        })
    }
    #run(){
        if (this.#state === PENDING) return
        
        while(this.#handler.length){
            const {onFulfilled, onRejected, resolve, reject} = this.#handler.shift()
    
            if (this.#state === FULFILLED) {
                this.#runCall(onFulfilled, resolve, reject)
                
            } else {
                this.#runCall(onRejected, resolve, reject)
            }

        }
    }

    then(onFulfilled, onRejected){
        return new MyPromise((resolve,reject) => {

          this.#handler.push({
            onFulfilled,
            onRejected,
            resolve,
            reject
          })

          this.#run() //recursion to avoid stack overflow.

        })
    }
    
    //MDN文档解释: 处理失败回调,处理方式与then方式一样
    catch(onRejected){
        return this.then(undefined, onRejected)
    }
    //无论成功失败都要执行这个回调
    finally(onFinally) {
        return this.then(
            data => {
                onFinally()  // MDN文档解释:onFinally他不接受任何参数,因为他不关心成功还是失败
                return data
            },
            (err) => {
                onFinally()
                throw err
            }
        )
    }
    //MDN文档解释:resolve,reject是一个静态方法
    static resolve(value){
        if (value instanceof MyPromise) return value
        let _resolve, _reject;
        const p =  new MyPromise((resolve, reject) => {  //静态方法事无法访问实例方法的 所以const p存
            _resolve = resolve; 
            _reject = reject;
        })
        if(p.#isPromiseLike(value)){
            value.then(_resolve, _reject) 
        }
        else {
            _resolve(value)
        }
        return p
    }

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

、
执行:
const p = new MyPromise((resolve,reject) => {
    resolve(1)
}) //constructor for a promise
p.then((val) => {
    console.log('data1',val)
    return 123
}).then((data) => {
    console.log('data2',data)
})

MyPromise.resolve(121212).then((data)=>{
   console.log(data)
})

输出:
[Running] node "d:\console\utils\myPromise.js"

data1 1
data2 123

121212

 

posted @ 2023-05-11 17:50  10后程序员劝退师  阅读(32)  评论(0)    收藏  举报