微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

javascript-ES6 Promise错误未按预期冒泡

我从E6 Promises开始.我非常喜欢它们,但是关于错误处理有一个至关重要的概念,我不了解,希望对此进行澄清.

让我们假设以下简单函数返回一个promise:

    function promiseString(str, timeout, doResolve) {
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                if (doResolve) {
                    resolve(str);
                } else {
                    reject(new Error("Rejecting " + str));
                }
            }, timeout);
        });
    }

这非常简单,只需返回传递给它的字符串的承诺,并导致该承诺在“超时”毫秒内被解析或拒绝(基于第三个参数).

我可以按预期完全使用此方法,如下所示:

            promiseString("One", 100, true)
                .then((str) => { console.log("First then is " + str); return promiseString(str + " two", 100, true); })
                .then((str) => { console.log("Second then is " + str); return promiseString(str + " three", 100, true); })
                .then((str) => console.log(str))
                .catch((err) => console.error(err));

如果在此链中的任何调用中将第三个参数从“ true”更改为“ false”,我的错误将按预期捕获并发送到console.error().

但是,现在想象一下以下(类似愚蠢的)函数用于构造有希望的对象:

    function DoublePromiser(str1, str2, doResolve) {
        this.promise = new Promise((resolve, reject) => {
            promiseString(str1, 100, doResolve)
                .then((s1) => promiseString(s1 + str2, 100, doResolve))
                .then((s2) => resolve(s2));
        });
    }

想象一下,现在我以如下方式使用此代码,所有代码都已解析且没有任何拒绝,(doResolve设置为true):

            var dp = new DoublePromiser("Big", "Promise", true);
            dp.promise
                .then((s) => console.log("DoublePromise: " + s))
                .catch((err)=>console.log("I did catch: ", err.message));

不出所料,我在控制台中看到以下内容

DoublePromise: BigPromise

但是,现在我更改了使用代码,将doResolve设置为“ false”(这会使我的promise例程拒绝):

            var dp = new DoublePromiser("Big", "Promise", false);
            dp.promise
                .then((s) => console.log("DoublePromise: " + s))
                .catch((err)=>console.log("I did catch: ", err.message));

因为我了解错误应该如何“冒泡”,所以我希望控制台记录如下:

I did catch: Rejecting Big

但事实并非如此.而是,控制台显示未捕获的错误

Uncaught (in promise) Error: Rejecting Big

如果在DoublePromiser的链的末尾添加一个catch,我只会得到我期望的(和期望的),就像这样:

    function DoublePromiser(str1, str2, doResolve) {
        this.promise = new Promise((resolve, reject) => {
            promiseString(str1, 100, doResolve)
                .then((s1) => promiseString(s1 + str2, 100, doResolve))
                .then((s2) => resolve(s2))
                .catch((err) => reject(err)); // ADDING THIS TO MAKE IT WORK
        });
    }

现在我得到了我所期望的,错误没有被发现.但这似乎与错误冒出来的整个想法背道而驰,并且发现错误只是为了重新拒绝相同的错误,这似乎很奇怪.

我是否错过了使它简单工作的方法

我是否缺少一些基本概念?

解决方法:

您正在使用promise构造函数反模式.不要将现有的承诺包装在您自己做的另一个承诺中,因为那样做会使您做很多额外的工作来使事情正常运行,并且由于大多数人没有正确地执行这些额外的工作,因此也很容易发生编程错误.只需返回您已经拥有的承诺即可.

更改此:

function DoublePromiser(str1, str2, doResolve) {
    this.promise = new Promise((resolve, reject) => {
        promiseString(str1, 100, doResolve)
            .then((s1) => promiseString(s1 + str2, 100, doResolve))
            .then((s2) => resolve(s2))
            .catch((err) => reject(err)); // ADDING THIS TO MAKE IT WORK
    });
}

对此:

function DoublePromiser(str1, str2, doResolve) {
    return promiseString(str1, 100, doResolve)
       .then((s1) => promiseString(s1 + str2, 100, doResolve));
}

然后,只需将其用作函数即可:

DoublePromiser("Big", "Promise", false).then(...);

回顾:您几乎总是想从.then()处理程序中返回内部的Promise,因为这允许嵌套的错误上传播,并且还可以正确地对异步操作进行链接/排序.

并且,您几乎要避免将新的Prom包装在现有Prom周围,因为您可以链接到和/或返回您已经拥有的现有Prom.

另外,请注意,如果执行.catch(),它将“处理”被拒绝的承诺并返回新的未拒绝的承诺,从那里继续执行承诺链,除非在.catch()处理程序内部返回了被拒绝的承诺或抛出异常.所以这:

p.catch((err) => console.log(err)).then(() => console.log("chain continues"))

会很高兴地执行两个console.log()语句,因为.catch()“处理”了诺言,因此诺言链愉快地继续了.

正如我在较早的评论中所说的那样,如果没有20页关于承诺如何工作的教程,其中涉及到很多内容,那么这些100%的理论讨论很难准确地达到您真正想要完成的目标(我们必须猜测真正的问题是什么).东西.如果您发布了您想使用此技术解决的现实问题,那就更好了,我们可以用几行代码和几段说明来展示/解释实现此问题的最佳方法.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐