Angular 1.6.0:"可能未处理的拒绝"错误

Gro*_*cho 66 javascript angularjs karma-runner angular-promise angularjs-1.6

我们在Angular应用程序中有一个解决承诺的模式,直到Angular 1.6.0为止我们一直很好:

    resource.get().$promise
        .then(function (response) {
        // do something with the response
        }, function (error) {
            // pass the error the the error service
            return errorService.handleError(error);
        });
Run Code Online (Sandbox Code Playgroud)

以下是我们如何在Karma中触发错误:

    resourceMock.get = function () {
        var deferred = $q.defer();
        deferred.reject(error);
        return { $promise: deferred.promise };
    };
Run Code Online (Sandbox Code Playgroud)

现在,随着1.6.0的更新,Angular突然抱怨我们的单元测试(在Karma中)因"可能未处理的拒绝"错误而被拒绝的承诺.但是我们正在处理调用错误服务的第二个函数中的拒绝.

Angular究竟在寻找什么?它是如何让我们"处理"拒绝的?

Cen*_*ael 65

尝试将此代码添加到您的配置中.我有一次类似的问题,这个解决方法就是这个伎俩.

app.config(['$qProvider', function ($qProvider) {
    $qProvider.errorOnUnhandledRejections(false);
}]);
Run Code Online (Sandbox Code Playgroud)

  • 我必须指出,这只是隐藏了错误,根据开发人员的说法,代码中存在一些问题,它只是掩盖了错误. (55认同)
  • 同意,虽然它可以避免问题,但根本原因仍然存在,开发人员应该处理错误情况。 (2认同)
  • 具体是什么配置文件? (2认同)

Lou*_*uis 22

您显示的代码将处理在调用之前发生的拒绝.then.在这种情况下,将调用您传递给的第二个回调.then,并将处理拒绝.

但是,当您呼叫的承诺.then成功时,它会调用第一个回调.如果此回调引发异常或返回被拒绝的承诺,则不会处理此结果拒绝,因为第二个回调不会处理第一个引起的拒绝.这就是承诺实现符合Promises/A +规范的工作方式,以及Angular承诺是否合规.

您可以使用以下代码说明这一点:

function handle(p) {
    p.then(
        () => {
            // This is never caught.
            throw new Error("bar");
        },
        (err) => {
            console.log("rejected with", err);
        });
}

handle(Promise.resolve(1));
// We do catch this rejection.
handle(Promise.reject(new Error("foo")));
Run Code Online (Sandbox Code Playgroud)

如果你在Node中运行它,它也符合Promises/A +,你得到:

rejected with Error: foo
    at Object.<anonymous> (/tmp/t10/test.js:12:23)
    at Module._compile (module.js:570:32)
    at Object.Module._extensions..js (module.js:579:10)
    at Module.load (module.js:487:32)
    at tryModuleLoad (module.js:446:12)
    at Function.Module._load (module.js:438:3)
    at Module.runMain (module.js:604:10)
    at run (bootstrap_node.js:394:7)
    at startup (bootstrap_node.js:149:9)
    at bootstrap_node.js:509:3
(node:17426) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2): Error: bar
Run Code Online (Sandbox Code Playgroud)

  • 好的,修复就像$ promise.then(成功).catch(错误),其中catch捕获所有错误,更多在[migration]的"Note"部分(https://docs.angularjs.org/guide/migration#migrate1 .5to1.6-NG-服务 - $ HTTP) (5认同)
  • 如何实际修复问模式代码? (3认同)
  • 如果您的函数按设计返回被拒绝的承诺怎么办?类似于 $http.get() 返回一个承诺的方式,如果请求失败,则按设计被拒绝。我有返回承诺的函数,在某些情况下它们可以返回 $q.reject(err),除非我破坏警告,否则 angular 似乎不喜欢这个? (2认同)

Gro*_*cho 18

通过回滚到Angular 1.5.9并重新运行测试找到了问题.这是一个简单的注入问题,但Angular 1.6.0通过抛出"可能未处理的拒绝"错误取代了这一点,混淆了实际的错误.


And*_*kyi 16

第一个选项只是通过errorOnUnhandledRejections按照建议配置$ qProvider配置来隐藏错误并禁用它Cengkuru Michael

这样只会关闭日志记录.错误本身将保留

在这种情况下,更好的解决方案是 - 使用.catch(fn)方法处理拒绝:

resource.get().$promise
    .then(function (response) {})
    .catch(function (err) {});
Run Code Online (Sandbox Code Playgroud)

链接:


小智 5

您可以通过关闭 errorOnUnhandledRejections 来掩盖问题,但错误表明您需要“处理可能的拒绝”,因此您只需要在承诺中添加一个捕获。

resource.get().$promise
    .then(function (response) {
    // do something with the response
    }).catch(function (error)) {
        // pass the error to the error service
        return errorService.handleError(error);
    });
Run Code Online (Sandbox Code Playgroud)

参考:https : //github.com/angular-ui/ui-router/issues/2889


Uri*_*zen 5

为了避免键入其他.catch(function () {})在多个地方的代码,您可以添加decorator$exceptionHandler

这是一个比其他选项更为冗长的选项,但您只需要在一个地方进行更改即可。

angular
    .module('app')
    .config(configDecorators);

configDecorators.$inject = ["$provide"];
function configDecorators($provide) {

    $provide.decorator("$exceptionHandler", exceptionHandler);

    exceptionHandler.$inject = ['$delegate', '$injector'];
    function exceptionHandler($delegate, $injector) {
        return function (exception, cause) {

            if ((exception.toString().toLowerCase()).includes("Possibly unhandled rejection".toLowerCase())) {
                console.log(exception); /* optional to log the "Possibly unhandled rejection" */
                return;
            }
            $delegate(exception, cause);
        };
    }
};
Run Code Online (Sandbox Code Playgroud)