手写Promise,1.5promise中then方法的链式调用识别Promise对象自身

HeiYanjing -
手写Promise,1.5promise中then方法的链式调用识别Promise对象自身

promise的then方法会返回一个promise对象。如果用户在写代码的过程中,将自身给返回出去,就会报类型错误。
测试代码:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset=UTF-8>
    <meta name=viewport content="width=device-width, initial-scale=1.0">
    <title>Promise.then方法返回自身测试</title>
</head>

<body>
    <script>
        var p = new Promise(function (resolve, reject) {
            resolve(100);
        })
        var p1 = p.then(function (value) {
            console.log(value)
            return p1;
        })
        p1.then(function () {}, function (resson) {
            console.log(resson.message)
        })
    </script>
</body>

</html>

在控制台中打印如下,提示循环调用。

100
Chaining cycle detected for promise #<Promise>

因此需要在之前的代码中做一下必要的判断。如果返回的是自身,就要报类型错误。
resolvePromise方法中加一个参数,将then方法中返回promise对象传入

function resolvePromise(promise2, e, resolve, reject) {
    if (promise2 === e) {
        return reject(new TypeError("Chaining cycle detected for promise #<Promise>"))
    }
    if (e instanceof MyPromise) {
        // promise对象
        // e.then((value) => {
        //     resolve(value)
        // }, (reason) => {
        //     reject(reason)
        // })
        // 简化代码
        e.then(resolve, reject);
    } else {
        //普通值
        resolve(e);
    }
}

但是这个代码是有问题的,resolvePromise方法存在于then方法中promise的执行器里面。而他的第一个参数却是promise对象的返回值,resolvePromise无法获取到这个返回值,这显然有问题。
解决方法就是将then方法中判断状态之后的逻辑代码编程异步代码,让所有的同步先执行,promise返回值就存在了。此时resolvePromise就能获取到new Promise的返回值。

            if (this.status === FULFILLED) {
                setTimeout(() => {
                    // 定义成功回调返回值,传给下一个then的成功回调
                    let successRtn = successCallback(this.value);
                    // 判断 x 的值是普通值还是promise对象
                    // 如果是普通值 直接调用resolve 
                    // 如果是promise对象 查看promsie对象返回的结果 
                    // 再根据promise对象返回的结果 决定调用resolve 还是调用reject
                    // 执行resolve方法,相当于把返回值传递给下一个then的成功回调函数
                    resolvePromise(promise2, successRtn, resolve, reject);
                }, 0);
            } 

测试代码修改一下

let promise = new MyPromise((resolve, reject) => {
    resolve('---success----');
})

let p1 = promise.then(value => {
    console.log(value);
    return p1;
}, reason => {
    console.log(reason)
})

p1.then(value => {
    console.log(value)
},reason=>{
    console.log(reason)
})

控制台打印

---success----
TypeError: Chaining cycle detected for promise #<Promise>

测试成功。

特别申明:本文内容来源网络,版权归原作者所有,如有侵权请立即与我们联系(cy198701067573@163.com),我们将及时处理。

Tags 标签

javascript前端es6node.js

扩展阅读

加个好友,技术交流

1628738909466805.jpg