【问题标题】:Check if a dependency is being injected in Angular检查是否在 Angular 中注入了依赖项
【发布时间】:2015-07-05 02:54:53
【问题描述】:

正如here 所讨论的那样,IE 在使用 ajax(即 $route 和 $http)时缓存内容很糟糕。可以在here 找到解决此问题的绝妙方法。

我们在我们的网站上使用 许多 Angular 应用程序,因此为了确保其他开发其他 Angular 应用程序的开发人员不会出现缓存问题,我想添加上述建议的解决方案当然,我们网站上的每个 Angular 应用程序。如果我们的样式指南包含以下内容,开发人员在构建自己的应用程序时更有可能包含它,并且可以成功避免非常危险的 IE 问题。毕竟,我认识的开发者已经不多了,积极使用 IE 进行开发。

var myApp = angular.module('myApp', ['ngRoute']);

myApp.config(['$routeProvider', '$httpProvider', function($routeProvider, $httpProvider) {
    $httpProvider.defaults.cache = false;
    if (!$httpProvider.defaults.headers.get) {
      $httpProvider.defaults.headers.get = {};
    }
    // disable IE ajax request caching
    $httpProvider.defaults.headers.get['If-Modified-Since'] = '0';
    // routes go here...
}]);

此代码的作用是强制 IE 不缓存模板并为 $http 调用发出服务器请求,而不是从其缓存中提取结果(如果您的数据是动态的,这可能非常糟糕——它很可能是)。

为每个 Angular 应用程序添加上述代码的问题在于,该应用程序可能会将 ngRoute 注入到应用程序的依赖项中,也可能不会。如果 ngRoute 不存在,则会发生注入错误。

所以,问题是这样的:是否可以检查 Angular 中是否存在注入的依赖项?我希望能够执行以下操作:

var myapp = angular.module('ordersApp', [
    'ngTouch',
    'ngRoute',
    'ngAnimate',
    'myController'
]);

if(myapp.has_ngRoute) {
     myapp.config(['$routeProvider', '$httpProvider', function($routeProvider, $httpProvider) {
    $httpProvider.defaults.cache = false;
         if (!$httpProvider.defaults.headers.get) {
             $httpProvider.defaults.headers.get = {};
         }
         // disable IE ajax request caching
        $httpProvider.defaults.headers.get['If-Modified-Since'] = '0';
        // routes go here...
    }]);
}

【问题讨论】:

    标签: javascript ajax angularjs internet-explorer caching


    【解决方案1】:

    有两种方法可以解决这个问题:

    1。检查服务是否存在并根据该服务运行行为

    这回答了您的具体问题 - 仅在服务存在时运行代码

    您可以使用$injector.has(...) 查看提供者/服务是否已注册。

    您可以检查$routeProvider 是否已注册,如果存在则配置 HTTP 标头。

    这是一个示例,我们在配置$httpProvider 之前检查$routeProvider

    // Cache configuration behaviour.
    var configureCache = ['$httpProvider', function($httpProvider) {
            $httpProvider.defaults.cache = false;
            if (!$httpProvider.defaults.headers.get) {
                $httpProvider.defaults.headers.get = {};
            }
            // disable IE ajax request caching
            $httpProvider.defaults.headers.get['If-Modified-Since'] = '0';
    }];
    
    
    angular.module('testApp', [
            // Test this by commenting this out.
            'ngRoute'
        ])
        .config(['$injector', function($injector){
            if ($injector.has('$routeProvider')){
                // If $routeProvider has been registered then
                // configure the $httpProvider.
                console.log('Has $routeProvider: configuring cache.');
    
                // Use `$injector.invoke(...)` so we can use
                // Angular dependency injection in our
                // configuration function above.
                $injector.invoke(configureCache);
            } else {
                // Otherwise don't do anything.
                console.log('Skipping cache configuration.');
            }
    }]);
    

    这是 Plunker 中的示例: http://plnkr.co/edit/orXOjMg0YZXDfwoqf9OD


    2。将代码拆分为模块

    不要检查模块/服务是否存在,而是使用模块依赖来控制它

    通过这种方法,我们获得了更大的灵活性。您定义缓存行为 在它自己的依赖于ngRoute的模块中。

    这样,当您包含缓存自定义行为时,您知道ngRoute 必须存在,因为它是依赖项之一!

    这为您提供了三种控制路由/缓存行为的方法 应用程序仅取决于您包含哪些模块:

    没有路线

    angular.module('testApp', [
            // Don't add 'ngRoute' module dependency here
            // or alter the caching behaviour.
        ])
    

    路由但具有默认缓存行为

    angular.module('testApp', [
            'ngRoute'
        ])
    

    具有自定义缓存行为的路由

    angular.module('testApp', [
            'noCacheRoutes'
        ])
    

    在每种情况下,我们只需要更改模块依赖项,但 以已知方式更改应用程序的行为。

    这里是拆分缓存配置行为的例子 进入一个单独的模块:

    /**
     * We decide that it only make sense to use this 
     * module along with `ngRoute` so define it as
     * a dependency here.
     */
    angular.module('noCacheRoutes', [
            'ngRoute'
        ])
        .config(['$httpProvider', function($httpProvider) {
            $httpProvider.defaults.cache = false;
            if (!$httpProvider.defaults.headers.get) {
                $httpProvider.defaults.headers.get = {};
            }
            // disable IE ajax request caching
            $httpProvider.defaults.headers.get['If-Modified-Since'] = '0';
        }]);
    
    
    /**
     * Don't reference `ngRoute` here, let `noCacheRoutes`
     * bring it in as a transitive dependency.
     * 
     * If later on you decide you don't need to change
     * the caching behaviour you can just replace `noCacheRoutes`
     * with `ngRoute` and don't need to make any further changes.
     */
    angular.module('testApp', [
            'noCacheRoutes'
        ])
        .config(['$routeProvider', function($routeProvider) {
            // Configure your application routes here.
        }]);
    

    【讨论】:

    • 这是一个很大的帮助!感谢@Sly_cardinal 非常详细和彻底的回复。我将按照您的建议将代码拆分为模块。按照您的建议,这似乎是保持灵活性的更好方法。
    【解决方案2】:

    正如AngularJs - get list of all registered modules 所讨论的,没有获取模块列表的方法,但您可以扩展 Angular 的模块方法(参见接受的答案)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-04-14
      • 2021-12-31
      • 2016-04-15
      • 2020-03-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多