为啥没有触发`.catch`回调

Posted

技术标签:

【中文标题】为啥没有触发`.catch`回调【英文标题】:Why is `.catch` callback not triggered为什么没有触发`.catch`回调 【发布时间】:2017-03-15 14:30:35 【问题描述】:

我有以下使用本机承诺的代码:

function getUser() 
    return new Promise(function (resolve, reject) 
        reject();
    );


function changeUser() 
    return new Promise(function (resolve, reject) 
        return getUser().catch(function (responseData, test) 
            console.log('boo error'); // this logs `boo error`
            throw ;
        );
    );


changeUser().then(function () 
    console.log('done');
).catch(function () 
    console.log('error'); // this is not triggered
);

当我运行它时,不执行带有console.log('error'); 的第一个catch 块。这是为什么?原生 Promise 的实现和Q 有区别吗?

【问题讨论】:

***.com/questions/33445415/…看看这个 【参考方案1】:

因为你从来没有reject 承诺你从changeUser 返回。你只是throwing 在从getUser 返回的承诺链中,它在该链中级联,但不影响在changeUser 中构造的new Promise

要么:

return new Promise(function (resolve, reject) 
    return getUser().then(resolve, function (responseData, test) 
        console.log('boo error'); // this logs `boo error`
        reject();
    );
);

或者:

function changeUser() 
    return getUser().catch(function (responseData, test) 
        console.log('boo error'); // this logs `boo error`
        throw ;
    );

【讨论】:

但是getUser().then(返回的promise不是像Q库那样变成new Promise返回的promise吗? 不,ECMAScript 标准 Promise 实现没有指定执行程序能够返回任何内容。您可以在 then 中“更新链”,而不是在构造函数中。 ecma-international.org/ecma-262/6.0/#sec-promise-executor 谢谢,所以 this answer 的行为谈到 下一个 then 子句将是函数返回的 promise 的 then 子句, 不适用于执行者,仅适用于 @ 987654335@方法? 它非常明确地讨论了 .then 处理程序中发生的事情,是的。 大多数情况下它没有多大意义。如果你从执行者那里做的只是返回一个不同的承诺,你为什么要实例化 new Promise 以开始......?【参考方案2】:

因为您在 changeUser 函数中嵌套了两个不同的承诺链。 resolvereject 函数永远不会在该函数中调用,因此 throw 不会冒泡。如果您在 Chrome 中执行此操作,您还会在控制台中收到“未捕获的承诺”消息。

通过以下方式修复它:

return new Promise(function (resolve, reject) 
    return getUser().catch(function (responseData, test) 
        console.log('boo error'); // this logs `boo error`
        throw ;
    ).then(resolve, reject);
);

或者完全删除return new Promise 行。

【讨论】:

删除return new Promise 是更好的解决方案,imo

以上是关于为啥没有触发`.catch`回调的主要内容,如果未能解决你的问题,请参考以下文章

为啥 catch 块不会触发并且应用程序停止在 node.js 中工作

为啥在 php 7 中添加回调类型提示会触发弃用警告

为啥间隔回调属于第一次渲染不能在每次间隔触发时向 React 发送更新指令(计数 +1)?

前端基础知识---Promise

为啥android的checkbox的setChecked方法不触发onCheckedChanged事件

订阅的节会触发回调吗?