简体   繁体   English

在拦截器内使用`$ mdToast`触发循环依赖

[英]Using `$mdToast` inside an interceptor triggering circular dependency

Question: 题:

How can I use $mdToast inside an interceptor without triggering the error? 如何在拦截器内使用$mdToast而不触发错误?

Setup: 建立:

Interceptor definition: 拦截器定义:

(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;
  }
})();

Interceptor config: 拦截器配置:

(function () {
  'use strict';

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

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

Issue: 问题:

When I load the application it triggers the following error: 当我加载应用程序时,它会触发以下错误:

Uncaught Error: [$injector:cdep] Circular dependency found: $http <- $templateRequest <- $$animateQueue <- $animate <- $$interimElement <- $mdToast <- HttpError500Interceptor <- $http <- $templateFactory <- $view <- $state 未捕获错误:[$ injector:cdep]找到循环依赖项:$ http < - $ templateRequest < - $$ animateQueue < - $ animate < - $$ interimElement < - $ mdToast < - HttpError500Interceptor < - $ http < - $ templateFactory < - $ view < - $ state

One work around that has helped me in the past is to use $injector to get your dependency at runtime instead of at configuration time. 过去帮助我的一个方法就是使用$injector来在运行时而不是在配置时获得依赖。 So, something like: 所以,像:

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

When your cyclic dependency does not cause problems, which it probably doesn't in this case, this will do the trick. 如果你的循环依赖不会导致问题,在这种情况下它可能不会出现问题,这将解决问题。

Neither of the provided solutions worked for me, so I'm posting here what I did so anyone with the same issue can have a range of workarounds to use. 这两个提供的解决方案都没有为我工作,所以我在这里发布了我所做的事情,因此任何有相同问题的人都可以使用各种解决方法。

What I really wanted was to have a common component to handle HTTP interceptors named interceptors and show the messages directly from the module, and happily, since the final solution is more elegant, it triggered this error while injecting the $mdToast service. 我真正想要的是拥有一个通用组件来处理名为interceptors HTTP拦截interceptors并直接从模块显示消息,并且很高兴,因为最终的解决方案更优雅,它在注入$mdToast服务时触发了这个错误。

The solution I came later, which I already said, is more elegant that my first fix to the issue is: 我后来提到的解决方案,更优雅,我对此问题的第一个解决方案是:

  • to have a common component to handle HTTP interceptors named interceptors , 有一个通用组件来处理名为interceptors HTTP拦截interceptors
  • to have a common component to handle global notifications named notifications-hub . 有一个通用组件来处理名为notifications-hub全局通知。

Then, in the interceptors module, I trigger a global event with: 然后,在interceptors模块中,我触发一个全局事件:

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

Then, in the notifications-hub module, I registered on the event and used the $mdToast , which was injected without errors in the notifications service: 然后,在notifications-hub模块中,我在事件上注册并使用$mdToast ,它在通知服务中注入时没有错误:

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

NotificationsHubService is the service injecting $mdToast . NotificationsHubService是注入$mdToast的服务。

Conclusion: 结论:

I used a global event as a glue between the low-level interceptors and the notifications subsystem to overcome the issue. 我使用全局事件作为低级拦截器和通知子系统之间的粘合剂来克服该问题。

Hopefully it will be of use for anyone else. 希望它对任何人都有用。

What you should do is create a function that brings you the toaster at run time 你应该做的是创建一个在运行时为你带来烤面包机的功能

  var getToaster = ()=>{

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

Now call it only when you need it - this will provide a work around the dependency circular 现在只在你需要时调用它 - 这将提供一个围绕依赖循环的工作

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM