promise架子及完成版

一、关于promise的架子

        根据​​​​​​​​​​​​​​Promises/A+写了一个关于promise的架子,这个架子将除了task和#Resolve以外的所有事情都做了。因为task运行时,promise一定已经完成了,所以task会很好写。可以先写task,最后再尝试#Resolve。当被要求手写一个promise时,这个架子会很有用。

class _Promise {
    #state = 'pending'
    #result = undefined

    #resolve
    #reject
    constructor(callback) {
        let setState = (state, result) => {
            this.#state = state
            this.#result = result
            setState = () => { }
            this.#run()
        }
        this.#resolve = value => setState('fulfilled', value)
        this.#reject = reason => setState('rejected', reason)
        callback(this.#resolve, this.#reject)
    }


    // 任务队列,promise到达最终状态前的所有任务都在其中
    #task_queue = []
    // 取出任务并执行
    #run() {
        let task
        while (task = this.#task_queue.shift()) task()
    }

    then(onFulfilled, onRejected) {
        const promise2 = new _Promise((resolve, reject) => {
            // task
            let task = () => { }
            this.#state === 'pending' ? this.#task_queue.push(task) : task()
        })
        // then方法返回一个promise
        return promise2
    }

    // #Resolve,task会用到
    #Resolve(promise, x) { }
}

二、完成版

class _Promise {
    #state = 'pending'
    #result = undefined

    #resolve
    #reject
    constructor(callback) {
        let setState = (state, result) => {
            this.#state = state
            this.#result = result
            setState = () => { }
            this.#run()
        }
        this.#resolve = value => setState('fulfilled', value)
        this.#reject = reason => setState('rejected', reason)
        callback(this.#resolve, this.#reject)
    }

    #task_queue = []
    #run() {
        let task
        while (task = this.#task_queue.shift()) task()
    }

    then(onFulfilled, onRejected) {
        const promise2 = new _Promise((resolve, reject) => {
            let task = () => {
                if (this.#state === 'fulfilled') {
                    if (typeof onFulfilled === 'function') {
                        queueMicrotask(() => {
                            try {
                                const x = onFulfilled(this.#result)
                                this.#Resolve(promise2, x)
                            } catch (error) {
                                reject(error)
                            }
                        })
                    } else resolve(this.#result)
                }

                if (this.#state === 'rejected') {
                    if (typeof onRejected === 'function') {
                        queueMicrotask(() => {
                            try {
                                const x = onRejected(this.#result)
                                this.#Resolve(promise2, x)
                            } catch (error) {
                                reject(error)
                            }
                        })
                    } else reject(this.#result)
                }
            }

            this.#state === 'pending' ? this.#task_queue.push(task) : task()
        })

        return promise2
    }

    #Resolve(promise, x) {
        if (promise === x) promise.#reject(new TypeError('promise 和 x 不能引用同一对象'))
        if (x instanceof _Promise) x.then(promise.#resolve, promise.#reject)
        if (typeof x === 'object' || typeof x === 'function') {
            let then
            try {
                then = x.then
            } catch (error) {
                promise.#reject(error)
            }

            if (typeof then === 'function') {
                let used = false
                let resolvePromise = y => {
                    if (used) return
                    this.#Resolve(promise, y)
                    used = true
                }
                let rejectPromise = r => {
                    if (used) return
                    promise.#reject(r)
                    used = true
                }

                try {
                    x.then(resolvePromise, rejectPromise)
                } catch (error) {
                    if (used) return
                    promise.#reject(error)
                }
            } else promise.#resolve(x)
        } else promise.#resolve(x)
    }
}

三、测试then

2.1

承诺必须处于以下三种状态之一:pending, fulfilledrejected

2.1.1

待处理时,promise:

        2.1.1.1

        可能会转换(过渡)为“已满足”或“已拒绝”状态。

    <script src="./_Promise.js"></script>
    <script>
        let p1 = new _Promise((resolve) => {
            setTimeout(() => {
                resolve()
                console.log(p1);
                console.log('p2======')
                let p2 = new _Promise((resolve,reject) => {
                    setTimeout(() => {
                        reject()
                        console.log(p2);
                    })
                })
                console.log(p2);
            })
        })
        console.log('p1======')
        console.log(p1);
    </script>

2.1.2

 实现(fulfilled)时的promise:

        2.1.2.1

        不得过渡到任何其他状态。

    <script src="./_Promise.js"></script>
    <script>
        let p1 = new _Promise((resolve, reject) => {
            setTimeout(() => {
                resolve()
                console.log('实现', p1);
                setTimeout(() => {
                    reject()
                    console.log('修改状态', p1);
                })
            })
        })
    </script>

        2.1.2.2

        必须有一个值,该值不得更改。

    <script src="./_Promise.js"></script>
    <script>
        let p1 = new _Promise((resolve, reject) => {
            resolve('1:初次传值')
            resolve('2:修改传值')
            reject('3:修改传值')
        })
        setTimeout(() => {
            console.log(p1);
        })
    </script>

2.1.3

当被拒绝(rejected)时,promise:

        2.1.3.1

        不得过渡到任何其他状态。

    <script src="./_Promise.js"></script>
    <script>
        let p1 = new _Promise((resolve, reject) => {
            setTimeout(() => {
                reject()
                console.log('拒绝', p1);
                setTimeout(() => {
                    resolve()
                    console.log('修改状态', p1);
                })
            })
        })
    </script>

        2.1.3.2

        必须有一个理由,这个理由不能改变。

    <script src="./_Promise.js"></script>
    <script>
        let p1 = new _Promise((resolve, reject) => {
            reject('1:初次给出理由')
            reject('2:修改理由')
            resolve('3:修改理由')
        })
        setTimeout(() => {
            console.log(p1);
        })
    </script>

2.2

promise 的 then 方法接受两个参数:

promise.then(onFulfilled, onRejected)

2.2.1

onFulfilled 和 onRejected 都是可选参数:

        2.2.1.1

        如果 onFulfilled 不是一个函数,则必须忽略它。

    <script src="./_Promise.js"></script>
    <script>
        let p = new _Promise((resolve, reject) => {
            resolve('value')
        })
        p.then('不是函数')
        console.log('正常运行');
        console.log(p);
    </script>

        2.2.1.2

        如果 onRejected 不是一个函数,则必须忽略它。

    <script src="./_Promise.js"></script>
    <script>
        let p = new _Promise((resolve, reject) => {
            reject('reason')
        })
        p.then(undefined,'不是函数')
        console.log('正常运行');
        console.log(p);
    </script>

2.2.2

如果 onFulfilled 是一个函数:

        2.2.2.1

        它必须在 promise 实现后调用,并将 promise 的值作为其第一个参数。

    <script src="./_Promise.js"></script>
    <script>
        let p = new _Promise((resolve, reject) => {
            setTimeout(() => {
                console.log('实现前');
                resolve('value')
                console.log('实现后');
            }, 1000)
        })
        p.then((res) => {
            console.log('被调用', res);
        })
    </script>

        2.2.2.2

        在promise实现之前,绝不能召唤它。

    <script src="./_Promise.js"></script>
    <script>
        let p = new _Promise((resolve, reject) => {
            setTimeout(() => {
                console.log('实现前');
                resolve('value')
                console.log('实现后');
            }, 1000)
        })
        p.then((res) => {
            console.log('被调用', res);
        })
    </script>

        2.2.2.3

        不得多次调用它。

    <script src="./_Promise.js"></script>
    <script>
        let p = new _Promise((resolve, reject) => {
            resolve('实现1')
            resolve('实现2')
            resolve('实现3')
        })
        let i = 1
        p.then((value) => {
            console.log('被调用%d次:%s', i++,value);
        })
    </script>

2.2.3

如果 onRejected 是一个函数,

        2.2.3.1

        它必须在 promise 被拒绝后调用,并将 promise 的理由作为其第一个参数。

    <script src="./_Promise.js"></script>
    <script>
        let p = new _Promise((resolve, reject) => {
            setTimeout(() => {
                console.log('拒绝前');
                reject('reason')
                console.log('拒绝后');
            }, 1000)
        })
        p.then(undefined,(reason) => {
            console.log('被调用', reason);
        })
    </script>

        2.2.3.2

        在 Promise 被拒绝之前,不得调用它。

    <script src="./_Promise.js"></script>
    <script>
        let p = new _Promise((resolve, reject) => {
            setTimeout(() => {
                console.log('拒绝前');
                reject('reason')
                console.log('拒绝后');
            }, 1000)
        })
        p.then(undefined,(reason) => {
            console.log('被调用', reason);
        })
    </script>

        2.2.3.3

        不得多次调用它。

    <script src="./_Promise.js"></script>
    <script>
        let p = new _Promise((resolve, reject) => {
            reject('拒绝1')
            reject('拒绝2')
            reject('拒绝3')
        })
        let i = 1
        p.then(undefined,(reason) => {
            console.log('被调用%d次:%s', i++,reason);
        })
    </script>

2.2.4

执行上下文堆栈仅包含平台代码之前,不得调用 onFulfilled 或 onRejected。

        let p1 = new _Promise((resolve, reject) => {
            resolve('value')
        })
        console.log('当前执行中%d...', 1);

        p1.then((value) => {
            console.log('实现:%s', value);
        })
        console.log('当前执行中%d...', 2);
        let p2 = new _Promise((resolve, reject) => {
            reject('value')
        })
        console.log('当前执行中%d...', 3);
        p2.then(undefined, (reason) => {
            console.log('拒绝:%s', reason);
        })
        console.log('当前执行中%d...', 4);
        console.log('当前执行中%d...', 5);
        console.log('执行完毕%d:______', 6);
    </script>

2.2.5

onFulfilled 和 onRejected 必须作为函数调用(即没有this值)。

<script src="./_Promise.js"></script>
    <!-- 非严格模式 -->
    <script>
        console.log(
            "%c 非严格模式",
            "color: yellow; font-style: italic; background-color: blue;padding: 2px",
        );
        let p1 = new _Promise((resolve, reject) => {
            resolve()
        })
        p1.then(() => {
            console.log('onFulfilled的%cthis:', 'color:blue');
            console.log(this);
        })
        let p2 = new _Promise((resolve, reject) => {
            reject()
        })
        p2.then(undefined, (reason) => {
            console.log('onRejected的%cthis:', 'color:blue');
            console.log(this);
        })
    </script>
    <!-- 严格模式 -->
    <script type="module">
        console.log(
            "%c 严格模式",
            "color: yellow; font-style: italic; background-color: red;padding: 2px",
        );
        let p1 = new _Promise((resolve, reject) => {
            resolve()
        })
        p1.then(() => {
            console.log('onFulfilled的%cthis:', 'color:blue');
            console.log(this);
        })
        let p2 = new _Promise((resolve, reject) => {
            reject()
        })
        p2.then(undefined, (reason) => {
            console.log('onRejected的%cthis:', 'color:blue');
            console.log(this);
        })
    </script>

2.2.6

then可能会在同一个 promise 上多次调用。

        2.2.6.1

        如果当 promise 被实现,所有相应的 onFulfilled 回调必须按照其原始调用的顺序执行到then

    <script src="./_Promise.js"></script>
    <script>
        let p = new _Promise((resolve, reject) => {
            setTimeout(() => {
                p.then(() => { console.log('第%d次调用then', 3); })
                p.then(() => { console.log('第%d次调用then', 4); })
                resolve()
                p.then(() => { console.log('第%d次调用then', 5); })
                p.then(() => { console.log('第%d次调用then', 6); })
            }, 500);
        })
        p.then(() => { console.log('第%d次调用then', 1); })
        p.then(() => { console.log('第%d次调用then', 2); })
    </script>

        2.2.6.2

        如果当 promise 被拒绝时,所有相应的 onRejected 回调必须按照其原始调用的顺序执行到then

    <script src="./_Promise.js"></script>
    <script>
        let p = new _Promise((resolve, reject) => {
            setTimeout(() => {
                p.then(undefined,() => { console.log('第%d次调用then', 3); })
                p.then(undefined,() => { console.log('第%d次调用then', 4); })
                reject()
                p.then(undefined,() => { console.log('第%d次调用then', 5); })
                p.then(undefined,() => { console.log('第%d次调用then', 6); })
            }, 500);
        })
        p.then(undefined,() => { console.log('第%d次调用then', 1); })
        p.then(undefined,() => { console.log('第%d次调用then', 2); })
    </script>

2.2.7

then必须返回一个 promise。

promise2 = promise1.then(onFulfilled, onRejected);

    <script src="./_Promise.js"></script>
    <script>
        const promise1 = new _Promise((resolve,reject)=>{})
        const promise2 = promise1.then();
        console.log(promise2);
    </script>

        2.2.7.1

        如果 onFulfilled 或 onRejected 返回值 x,则运行 Promise 解析过程 [[Resolve]](promise2, x)。转到:四(测试#Resolve)

   2.2.7.2

   如果 onFulfilled 或 onRejected 抛出异常 e,则必须以 e 为原因拒绝 promise2

    <script src="./_Promise.js"></script>
    <script>
        const promise1 = new _Promise((resolve, reject) => { resolve() })
        const promise2 = promise1.then(() => {
            throw new Error('onFulfilled:异常')
        });
        promise2.then(undefined, console.log)

        const promise3 = new _Promise((resolve, reject) => { reject() })
        const promise4 = promise3.then(undefined,() => {
            throw new Error('onRejected:异常')
        });
        promise4.then(undefined, console.log)
    </script>

        2.2.7.3

        如果 onFulfilled 不是函数,并且 promise1 已实现,则 promise2 必须使用与 promise1 相同的值实现。

    <script src="./_Promise.js"></script>
    <script>
        const promise1 = new _Promise((resolve, reject) => {
            setTimeout(() => {
                resolve('实现,value')
                console.log('promise2',promise2);
            })
        })
        const promise2 = promise1.then('我(onFulfilled)不是函数');
    </script>

        2.2.7.4

        如果 onRejected 不是函数并且 promise1 被拒绝,则必须以与 promise1 相同的原因拒绝 promise2

    <script src="./_Promise.js"></script>
    <script>
        const promise1 = new _Promise((resolve, reject) => {
            setTimeout(() => {
                reject('拒绝,reason')
                console.log('promise2',promise2);
            })
        })
        const promise2 = promise1.then(undefined,'我(onRejected)不是函数');
    </script>

四、测试#Resolve

2.3.1

如果 promise 和 x 引用同一对象,则拒绝 promise,并给出 TypeError 作为原因。

    <script src="./_Promise.js"></script>
    <script>
        const promise1 = new _Promise((resolve, reject) => { resolve() })
        const promise2 = promise1.then(() => promise2);
        setTimeout(() => { console.log(promise2) })

        const promise3 = new _Promise((resolve, reject) => { reject() })
        const promise4 = promise3.then(undefined, () => promise4);
        setTimeout(() => { console.log(promise4) })
    </script>

2.3.2

如果 x 是 promise,则采用其状态 :

        2.3.2.1

        如果 x 处于待处理状态,则 promise 必须保持待处理状态,直到 x 被实现或拒绝。

    <script>
        const promise1 = new _Promise((resolve, reject) => { resolve() })
        const x = new _Promise(()=>{})
        const promise = promise1.then(() => x);
        console.log(promise);  
    </script>

        2.3.2.2

        如果当 x 实现时,以相同的值实现promise。

    <script src="./_Promise.js"></script>
    <script>
        const promise1 = new _Promise((resolve, reject) => { resolve() })
        const x = new _Promise((resolve) => { resolve('x实现,value') })
        const promise = promise1.then(() => x);
        setTimeout(() => { console.log(promise); })
    </script>

        2.3.2.3

        如果当 x 被拒绝时,以同样的原因拒绝 promise

    <script src="./_Promise.js"></script>
    <script>
        const promise1 = new _Promise((resolve, reject) => { resolve() })
        const x = new _Promise((resolve,reject) => { reject('x拒绝,reason') })
        const promise = promise1.then(() => x);
        setTimeout(() => { console.log(promise); })
    </script>

2.3.3

否则,如果 x 是对象或函数

        2.3.3.1

        设 then 为 x.then

        2.3.3.2

        如果检索属性 x.then 导致抛出异常 e,则拒绝以 e 为原因的 promise

    <script src="./_Promise.js"></script>
    <script>
        const promise1 = new _Promise((resolve, reject) => { resolve() })
        const x = Object.defineProperty({}, 'then', {
            get() {
                throw new Error('不能访问then')
            }
        })
        const promise = promise1.then(() => x);
        setTimeout(() => { console.log(promise); })
    </script>

        2.3.3.3

        如果 then 是一个函数,则使用 x 调用它,第一个参数 resolvePromise,第二个参数 rejectPromise,其中:

    <script src="./_Promise.js"></script>
    <script>
        const promise1 = new _Promise((resolve, reject) => { resolve() })
        const x = {
            then(resolvePromise, rejectPromise) {
                console.log('resolvePromise', resolvePromise);  
                console.log('rejectPromise', rejectPromise);  
            }
        }
        const promise = promise1.then(() => x);
    </script>
     2.3.3.3.1

                如果当使用值 y 调用 resolvePromise,则运行 [[Resolve]](promise, y)。

     2.3.3.3.2

     如果当使用原因 r 调用 rejectPromise,则使用 r 拒绝 promise

    <script src="./_Promise.js"></script>
    <script>
        const promise1 = new _Promise((resolve, reject) => { resolve() })
        const x = {
            then(resolvePromise, rejectPromise) {
                rejectPromise('拒绝,r')
            }
        }
        const promise = promise1.then(() => x);
        setTimeout(() => { console.log(promise); })
    </script>

                2.3.3.3.3

                如果同时调用了 resolvePromise 和 rejectPromise,或者对同一参数进行了多次调用,则第一个调用优先,并且将忽略任何进一步的调用。

    <script src="./_Promise.js"></script>
    <script>
        const promise1 = new _Promise((resolve, reject) => { resolve() })
        const x = {
            then(resolvePromise, rejectPromise) {
                resolvePromise('第1个调用,实现,y')
                rejectPromise('第2个调用,拒绝,r')
                resolvePromise('第3个调用,实现,y')
                rejectPromise('第4个调用,拒绝,r')
            }
        }
        const promise = promise1.then(() => x);
        setTimeout(() => { console.log(promise); })
    </script>

                2.3.3.3.4

                如果调用then抛出异常 e

                        2.3.3.3.4.1

                        如果已调用 resolvePromise 或 rejectPromise,请忽略它。

    <script src="./_Promise.js"></script>
    <script>
        const promise1 = new _Promise((resolve, reject) => { resolve() })
        const x = {
            then(resolvePromise, rejectPromise) {
                resolvePromise('已调用resolvePromise') //rejectPromise同理
                throw new Error('异常')
            }
        }
        const promise = promise1.then(() => x);
        setTimeout(() => { console.log(promise); })
    </script>

                        2.3.3.3.4.2

                        否则,拒绝以 e 为原因的 promise

    <script src="./_Promise.js"></script>
    <script>
        const promise1 = new _Promise((resolve, reject) => { resolve() })
        const x = {
            then(resolvePromise, rejectPromise) {
                throw new Error('异常')
                resolvePromise('在异常后')
            }
        }
        const promise = promise1.then(() => x);
        setTimeout(() => { console.log(promise); })
    </script>

                2.3.3.4

                如果 then 不是一个函数,则用 x 实现promise

    <script src="./_Promise.js"></script>
    <script>
        const promise1 = new _Promise((resolve, reject) => { resolve() })
        const x = {
            name:'x',
            then: 'x.then:我不是函数'
        }
        const promise = promise1.then(() => x);
        setTimeout(() => { console.log(promise); })
    </script>

        2.3.4

        如果 x 不是对象或函数,则用 x 实现承诺

    <script src="./_Promise.js"></script>
    <script>
        const promise1 = new _Promise((resolve, reject) => { resolve() })
        const x = 'x:我不是对象,也不是函数'
        const promise = promise1.then(() => x);
        setTimeout(() => { console.log(promise); })
    </script>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值