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

IT技术 javascript angularjs karma-runner angular-promise angularjs-1.6
2021-03-13 06:09:51

在 Angular 应用程序中,我们有一个解决 promise 的模式,在 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);
        });

以下是我们在 Karma 中触发错误的方式:

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

现在,随着 1.6.0 的更新,Angular 突然在我们的单元测试中(在 Karma 中)抱怨被拒绝的Promise并出现“可能未处理的拒绝”错误。但是我们正在调用我们的错误服务的第二个函数中处理拒绝。

Angular 到底在寻找什么?它希望我们如何“处理”拒绝?

6个回答

尝试将此代码添加到您的配置中。我曾经遇到过类似的问题,这个解决方法成功了。

app.config(['$qProvider', function ($qProvider) {
    $qProvider.errorOnUnhandledRejections(false);
}]);
我必须指出,这只是隐藏了错误,据开发人员称,代码存在一些问题,它只是掩盖了错误。
2021-05-06 06:09:51
同意,虽然它可以避免问题,但根本原因仍然存在,开发人员应该处理错误情况。
2021-05-06 06:09:51
具体是什么配置文件?
2021-05-16 06:09:51

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

但是,当您调用的Promise.then成功时,它会调用第一个回调。如果此回调引发异常或返回被拒绝的Promise,则不会处理由此产生的拒绝,因为第二个回调不会处理由第一个引起的拒绝。这就是符合Promises/A+规范Promise实现的工作方式,而 Angular 的 Promise 也是兼容的。

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

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")));

如果你在 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
这真的应该是正确答案
2021-04-21 06:09:51
好分!是的,目的是处理在调用 .then 之前发生的拒绝。触发此拒绝的代码(适用于 Angular 1.5.9)已添加到原始问题中。
2021-04-25 06:09:51
如何实际修复询问的模式代码?
2021-04-28 06:09:51
好的,修复就像 $promise.then(success).catch(error),其中 catch 捕获所有错误,更多信息请参见迁移时的“注意”部分
2021-05-01 06:09:51
如果您的函数按设计返回被拒绝的Promise怎么办?类似于 $http.get() 返回一个Promise的方式,如果请求失败,则按设计被拒绝。我有返回Promise的函数,在某些情况下它们可以返回 $q.reject(err),除非我破坏警告,否则 angular 似乎不喜欢这个?
2021-05-05 06:09:51

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

这样只会关闭日志记录。错误本身将仍然存在

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

resource.get().$promise
    .then(function (response) {})
    .catch(function (err) {});

链接:

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

这对我来说是一个大问题,因为我正在迁移代码库并替换旧的注入依赖项。你有没有找到一种方法来防止这种混淆并让它抛出真正的错误?
2021-04-30 06:09:51
上面的最佳答案将在运行代码中修复它,但我无法让它在不回滚到 Angular 1.5.9 的情况下在 Karma 中抛出错误。
2021-05-03 06:09:51

为避免.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);
        };
    }
};