当前位置: 首页 > 面试题库 >

具有全局$ http错误处理的AngularJS

仇航
2023-03-14
问题内容

我想全局拦截某些$http错误情况,以防止控制器自己处理错误。我认为我需要HTTP拦截器,但是我不确定如何从我的控制器中处理错误。

我有一个像这样的控制器:

function HomeController($location, $http) {
    activate();

    function activate() {
        $http.get('non-existent-location')
            .then(function activateOk(response) {
                alert('Everything is ok');
            })
            .catch(function activateError(error) {
                alert('An error happened');
            });
    }
}

和这样的HTTP拦截器:

function HttpInterceptor($q, $location) {
    var service = {
        responseError: responseError
    };

    return service;

    function responseError(rejection) {
        if (rejection.status === 404) {
            $location.path('/error');
        }
        return $q.reject(rejection);
    }
}

这与浏览器重定向到“ /错误”路径一样有效。但在承诺抓HomeController 执行了,我不希望这样。

我知道我可以编写代码HomeController,使其忽略404错误,但这是无法维护的。假设我进行修改HttpInterceptor以同时处理500个错误,那么我将不得不HomeController再次进行修改(以及以后可能添加的其他所有使用的控制$http)。有没有更优雅的解决方案?


问题答案:

的微小变化HttpInterceptor可以破坏/取消承诺链,这意味着将不执行activateOkactivateError不执行控制器。

function HttpInterceptor($q, $location) {
    var service = {
        responseError: responseError
    };

    return service;

    function responseError(rejection) {
        if (rejection.status === 404) {
            $location.path('/error');
            return $q(function () { return null; })
        }
        return $q.reject(rejection);
    }
}

return $q(function () { return null; }),取消承诺。

这是否“可以”是一个争论的话题。“ 您不了解JS ”中的Kyle
Simpson 指出:

许多Promise抽象库都提供了取消Promises的工具,但这是一个糟糕的主意!许多开发人员希望Promises本身具有外部取消功能,但是问题在于,这将使Promise的一个消费者/观察者影响其他消费者观察该Promise的能力。这违反了未来价值的可信赖性(外部不变性),但更体现了“远距离行动”反模式的体现。

好?坏?正如我所说,这是一个辩论话题。我喜欢这样的事实,它不需要更改任何现有的$http消费者。

凯尔说的很对:

许多Promise抽象库提供了取消Promises的工具。

例如,Bluebird
Promise库支持取消。从文档中:

新的取消具有“无关”语义,而旧的取消具有中止语义。取消promise只是意味着不会调用其处理程序回调。

选项2-不同的抽象

承诺是一个相对广泛的抽象。根据Promises / A +规范:

一个 promise 表示异步操作的最终结果。

Angular $http服务使用$qpromise 的实现为异步HTTP请求的最终结果返回promise。

这是值得什么,$http有2个废弃的函数,.success并且.error,其装饰返回的承诺。这些功能已被弃用,因为它们不能以promise的典型方式链接,并且被认为不会为“
HTTP特定”功能集增加太多价值。

但这并不是说我们无法创建自己的HTTP抽象/包装器,而该抽象器/包装器甚至没有公开所使用的底层承​​诺$http。像这样:

function HttpWrapper($http, $location) {
    var service = {
        get: function (getUrl, successCallback, errorCallback) {
            $http.get(getUrl).then(function (response) {
                successCallback(response);
            }, function (rejection) {
                if (rejection.status === 404) {
                    $location.path('/error');
                } else {
                    errorCallback(rejection);
                }
            });
        }
    };

    return service;
}

由于这不能兑现承诺,因此其消费也需要有所不同:

HttpWrapper.get('non-existent-location', getSuccess, getError);

function getSuccess(response) {
    alert('Everything is ok');
}

function getError(error) {
    alert('An error happened');
}

在404的情况下,位置被改变为“错误”,并且既不getSuccess也不getError回调被执行。

此实现意味着链接HTTP请求的功能不再可用。这是可以接受的折衷办法吗?结果可能会有所不同…

选项3-装饰拒绝

感谢TJ的评论:

如果您需要在特定控制器中处理错误,则需要条件来检查拦截器/服务等中是否已处理错误

HTTP拦截器可以用一个属性handled来装饰Promise拒绝,以指示它是否处理了错误。

function HttpInterceptor($q, $location) {
    var service = {
        responseError: responseError
    };

    return service;

    function responseError(rejection) {
        if (rejection.status === 404) {
            $location.path('/error');
            rejection.handled = true;
        }

        return $q.reject(rejection);
    }
}

控制器然后看起来像这样:

$http.get('non-existent-location')
    .then(function activateOk(response) {
        alert('Everything is ok');
    })
    .catch(function activateError(error) {
        if (!error.handled) {
            alert('An error happened');
        }
    });

摘要

与选项2不同,选项3仍然为所有$http消费者提供了兑现承诺的选项,这在不消除功能的意义上是积极的。

选项2和3的“远距离动作”较少。在选项2的情况下,替代抽象清楚地表明,事情的行为将与通常的$q实现有所不同。对于选项3,消费者仍将根据自己的喜好做出承诺。

这三个选项均满足可维护性标准,因为更改全局错误处理程序以处理或多或少的情况不需要更改使用者。



 类似资料:
  • 问题内容: 当我的网站是100%jQuery时,我曾经这样做: 为401错误设置全局处理程序。现在,我将angularjs与和一起使用,以向服务器发送(REST)请求。有什么办法可以类似地用角度设置全局错误处理程序吗? 问题答案: 我还在建立一个带有angular的网站,并且遇到了同样的障碍来处理全局401。当我遇到此博客文章时,我最终使用了HTTP拦截器。也许您会发现它和我一样有用。 “基于An

  • 我正在使用Apollo与用React编写的Web应用程序中的GraphQL服务器进行交互。我试图在应用程序中实现错误处理,并依赖于apollo-link-error。 现在,我需要处理两类错误: 可以在执行Apollo查询或变异的组件中本地处理的错误,即需要在其上显示上下文错误信息的无效表单字段 可以全局处理的错误,例如,通过在页面的某个位置显示toast通知来显示错误详细信息 显然,一旦错误在本

  • 我正在尝试修复VueJS SPA中出现的一种行为,其中出现了一种不稳定状态。应用程序不知道JWT已经过期,因此呈现出用户仍在登录的样子。例如,这可能发生在Hibernate之后。 这些用户可以继续向API发出任何请求,但最终会得到响应(这是正确的)。 我想要一个响应的全局处理程序。(这将是:从vuex清除所有与用户相关的内容,并将页面呈现为用户是访客,并弹出登录表单等。)否则,我将不得不为每个请求

  • 我使用spring-boot-starter-amqp1.4.2.Producer和消费者工作正常,但有时传入的JSON消息语法不正确。这会导致以下(正确)异常: 未来我可能会面临更多的例外。因此,我想配置一个全局错误处理程序,这样,如果任何一个消费者中存在任何异常,我就可以全局处理它。 注意:在这种情况下,消息根本没有到达消费者。我想在消费者中全局处理这类异常。 请找到以下代码: RabbitC

  • 问题内容: 有没有一种方法可以添加一个全局包罗万象的错误处理程序,可以在其中将响应更改为通用JSON响应? 我无法使用该信号,因为它不允许修改响应(http://flask.pocoo.org/docs/0.10/signals/)。 相反,所有信号处理程序均以未定义的顺序执行,并且不修改任何数据。 我宁愿不要包装该函数,因为感觉就像是内部API。我想我正在寻找类似的东西: 请注意,不会接受任何参

  • 问题内容: 我有2 ng-包括HTML。考虑服务器中是否不存在ng-include src之一。截至目前,它只会加载空白html,并且在浏览器控制台中会显示未找到http-404文件。 因此,在这种情况下,我只想将默认错误页面(服务器中存在)加载到该特定div中,即一半显示默认错误页面,另一部分显示通过nginclude加载的正确div。 我的逻辑是,使用HTTP拦截器拦截所有HTTP调用。无论何