【问题标题】:Using `$mdToast` inside an interceptor triggering circular dependency在触发循环依赖的拦截器中使用“$mdToast”
【发布时间】:2018-02-18 15:43:00
【问题描述】:

问题:

如何在拦截器中使用$mdToast 而不触发错误?

设置:

拦截器定义:

(function () {
  'use strict';

  angular
    .module('app.components.http-errors-interceptors')
    .factory('HttpError500Interceptor', HttpError500Interceptor);

  /* @ngInject */
  function HttpError500Interceptor($q,
                                   $mdToast,
                                   $filter) {

    var interceptor           = {};
    interceptor.responseError = responseError;

    function responseError(responseError) {
      if (responseError.status === 500) {
        $mdToast.show($mdToast.simple()
                              .content($filter('translate')('APP.COMPONENTS.HTTP_ERRORS_INTERCEPTORS.500'))
                              .position('bottom right')
                              .hideDelay(5000));
      }
      return $q.reject(responseError);
    }

    return interceptor;
  }
})();

拦截器配置:

(function () {
  'use strict';

  angular
    .module('app.components.http-errors-interceptors')
    .config(moduleConfig);

  /* @ngInject */
  function moduleConfig($httpProvider) {
    $httpProvider.interceptors.push('HttpError500Interceptor');
  }
})();

问题:

当我加载应用程序时,它会触发以下错误:

未捕获的错误:[$injector:cdep] 找到循环依赖:$http

【问题讨论】:

  • 你找到解决方法了吗?
  • @KumarSambhav 是的,我能够解决这个问题,请参阅下面的答案以适合您的特定用例。

标签: javascript angularjs circular-dependency angular-http-interceptors angularjs-material


【解决方案1】:

过去对我有帮助的一个解决方法是使用$injector 在运行时而不是在配置时获取依赖项。所以,类似:

  /* @ngInject */
  function HttpError500Interceptor($q,
                                   $injector,
                                   $filter) {
    function responseError(responseError) {
      var $mdToast = $injector.get('$mdToast');

当您的循环依赖不会导致问题时(在这种情况下可能不会),这会解决问题。

【讨论】:

  • 对不起,我已经试过了,没有用,触发同样的错误。还有其他想法吗?这让我发疯了。
  • 嗯。我无法解释。这应该打破依赖链。你确定这是完全相同的错误吗?
  • 是的:Uncaught Error: [$injector:cdep] Circular dependency found: $http <- $templateRequest <- $$animateQueue <- $animate <- $$interimElement <- $mdToast <- HttpError500Interceptor <- $http <- $templateFactory <- $view <- $state
  • 当您实际删除该依赖项并在运行时获取它时,$mdToast <- HttpError500Interceptor 怎么能做到? $injector.get 调用不会添加依赖项。也许看看 @ngInject 是否没有生成该依赖项。
  • 不要将此行var $mdToast = $injector.get('$mdToast'); 直接放在拦截器函数中。放在responseError函数里面,这样就不会导致循环依赖错误。
【解决方案2】:

所提供的解决方案都不适合我,所以我在这里发布我所做的,以便遇到相同问题的任何人都可以使用一系列解决方法。

我真正想要的是有一个通用组件来处理名为 interceptors 的 HTTP 拦截器并直接显示来自模块的消息,很高兴,由于最终的解决方案更优雅,它在注入 @987654322 时触发了这个错误@服务。

我后来提出的解决方案(我已经说过)比我对这个问题的第一个解决方案更优雅:

  • 拥有一个通用组件来处理名为 interceptors 的 HTTP 拦截器,
  • 拥有一个通用组件来处理名为notifications-hub 的全局通知。

然后,在interceptors 模块中,我触发了一个全局事件:

$rootScope.$broadcast('notifications:httpError', responseError);

然后,在notifications-hub 模块中,我注册了事件并使用了$mdToast,它在通知服务中注入时没有错误:

$rootScope.$on('notifications:httpError', function (event, responseError) { NotificationsHubService.processErrorsAndShowToast(responseError); });

NotificationsHubService是注入$mdToast的服务。

结论:

我使用全局事件作为低级拦截器和通知子系统之间的粘合剂来解决这个问题。

希望它对其他人有用。

【讨论】:

  • 根据单一职责的原则,这似乎是一个更正确和优雅的解决方案。
【解决方案3】:

你应该做的是创建一个在运行时为你带来烤面包机的函数

  var getToaster = ()=>{

    var toaster = $injector.get('$mdToaster');
    return toaster;
}

现在只在需要时调用它——这将提供一个解决依赖循环的方法

【讨论】:

猜你喜欢
  • 2022-01-13
  • 2016-02-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多