使用 $injector.get() 在 Angular 中获取我的依赖项有什么缺点吗?

Is there any downside to using $injector.get() to get my dependencies in Angular?

本文关键字:我的依赖 什么 缺点 获取 get injector Angular 使用      更新时间:2023-09-26

我的团队希望转向一种更接近Angular代码库的CommonJS/Node JS语法的依赖注入风格:

var myDependency = require('myDependency');

我已经开始在我的函数顶部直接使用 $injector.get(),到目前为止没有明显的麻烦。 这意味着我已经转换了这个:

angular.module('modD', ['modA', 'modB', 'modC'])
.service('serviceD', ['serviceA', 'serviceB', 'serviceC', function(serviceA, serviceB, serviceC) {
  //My code here
}])

到:

angular.module('modD', ['modA', 'modB', 'modC'])
.service('serviceD', ['$injector', function($injector) {
  var serviceA = $injector.get('serviceA');
  var serviceB = $injector.get('serviceB');
  var serviceC = $injector.get('serviceC');
  //My code here
}]);

我错过了什么吗? 不在函数定义之外声明所需的依赖项是否会导致任何类型的性能问题?

注意:此答案尚未经过测试。在深入研究了角度的代码后,我发现:

// in function createInjector
function provider(name, provider_) {
    ...
    if (isFunction(provider_) || isArray(provider_)) {
      provider_ = providerInjector.instantiate(provider_);
    }
    ...
    return providerCache[name + providerSuffix] = provider_;
}
...
function factory(name, factoryFn, enforce) {
    return provider(name, {
      $get: enforce !== false ? enforceReturnValue(name, factoryFn) : factoryFn
    });
}
function service(name, constructor) {
    return factory(name, ['$injector', function($injector) {
        return $injector.instantiate(constructor);
    }]);
}
...
// in function createInternalInjector
function invoke (...){
    ...
  for (i = 0, length = $inject.length; i < length; i++) {
    args.push(
      locals && locals.hasOwnProperty(key)
      ? locals[key]
      : getService(key, serviceName)
    );
  }
    ...
    return fn.apply(self, args);
}
function instantiate(...){
    ...
    var instance = Object.create((isArray(Type) ? Type[Type.length - 1] : Type).prototype || null);
    var returnedValue = invoke(Type, instance, locals, serviceName);
    return isObject(returnedValue) || isFunction(returnedValue) ? returnedValue : instance;
}
...
return {
    invoke: invoke,
    instantiate: instantiate,
    get: getService,
    annotate: createInjector.$$annotate,
    has: function(name) {
      return providerCache.hasOwnProperty(name + providerSuffix) || cache.hasOwnProperty(name);
    }
};

它的调用似乎是:

  • service调用factory调用instantiate
  • factory调用provider调用instantiate

所以我认为你的问题等于 一个接一个地调用 $injector.get(( 与调用一次 $injector.instantiate(( 的性能相同吗?

如代码所示,instantiate调用了invoke,这些实际上为您注入的每个服务调用了getService。而$injector.get只是与getService绑定.

所以我的平等问题的答案是真的

您的问题的答案是否定的,它们的性能非常接近

如果我错了,请纠正我,谢谢!

在服务的情况下,两段代码之间没有显着差异。 $injector.get(...)调用不提供任何开销。但它为每个依赖项提供了大量额外的字符。

当使用具有本地依赖项的可注射对象(控制器和路由/状态解析器(执行相同的操作时,会有所不同。

当这些依赖关系

app.controller('SomeCtrl', function ($scope, service) { ... });

被替换为$injector.get(...),它会窒息$scope - 它是本地依赖。随着其他依赖项的检索,控制器将失去其可测试性。不能用 模拟依赖项

$controller('SomeCtrl', { service: mockedService });

我个人看不出$injector.get(...)如何有益于项目的风格(并且还没有看到一个好的风格指南来建议它(。

Node使用require函数是因为它适合它,而不是因为它更好或更酷。另一种方法是将每个 Node 脚本打包到类似 AMD 的包装器中,这将是痛苦的。幸运的是,我们已经有了围绕 Angular 单元的包装器!