AngularJS将工厂注入提供者

AngularJS injecting a factory into a provider

本文关键字:提供者 注入 工厂 AngularJS      更新时间:2023-09-26

我正在构建一个模块,该模块必须使用provider配方,因为它需要在运行前进行配置。我对模块化我的代码很感兴趣,所以我想向提供者注入一些服务。我知道将providers注入到其他providers中很简单,但对于我试图实现的目标来说似乎有些过头了,所以我想注入一个factory

据我所知,在运行时使用$injector可以通过angular的createInternalInjector方法访问instanceCache,该方法返回已实例化的服务。

在配置阶段使用$injector时,您可以访问包含未实例化服务的providerCache

不过我觉得这个假设一定是不正确的。在下面的代码中,$injector在提供程序中使用,但通过在应用程序运行阶段调用的函数使用。我希望访问instanceCache,但我只能通过$injector.get方法访问providerCache

_tudModule.factory('wfTabletUsageDataCache', [
        function () {
            return {
                addToLog: fn () { … }
            }
        }
])

_tudModule.provider('$tabletUsageData', [
    '$injector', function $tabletUsageDataProvider ($injector) {
    function getCacheFactory() {
       return $injector.get('wfTabletUsageDataCacheProvider').$get();
    }
    function logInteraction(state, buttonId) {
        getCacheFactory().addToLog();           // fn() called
    }
]);

provider中的$injector禁用对instanceCache的访问?即使在config阶段没有运行提供程序中的方法?

此外,我以前还没有见过我使用$injector.get('wfTabletUsageDataCacheProvider').$get()的方法。尽管它有效,但这是实现此类功能的糟糕方法吗?

谢谢你的指示。

在配置阶段,(config()块或提供程序)可以注入提供程序常量,而不是工厂、服务或值。如果提供者对你来说太过分了,你可以使用常量。

像这样的东西可以工作

_tudModule.constant('wfTabletUsageDataCache', {
  addToLog: function () { ... }
});
_tudModule.provider('$tabletUsageData', [ 'wfTabletUsageDataCache',
  function (wfTabletUsageDataCache) {
     wfTabletUsageDataCache.addToLog(...)
  }
]);

在配置阶段使用$injector时,您可以访问包含未实例化服务的providerCache

看起来你是对的,但这种用法是没有记录的,通常是不鼓励的$injector是一个服务,不应该将其注入到提供者中


此外,我以前还没有见过我使用$injector.get('...').$get()的方法。

提供者是定义Angular服务的最低级别方式。所有.service().factory().value()定义都可以使用.provider()重写。根据定义,当提供者被实例化时,它必须公开一个$get方法,该方法是可注入的,并负责返回服务的实例。

这就是你在这里看到的。您使用$injector.get(...)检索(并实例化)提供程序,然后使用$get()方法创建服务实例。然而,这通常发生在后台,并且$get()方法不意味着要手动调用

您实际上是在试图绕过不允许在运行阶段之前实例化服务的限制。不建议这样做。

您的假设是正确的。您忽略的是有两个不同的注入器,分别用于服务提供者和服务实例。一旦您将提供者注入器注入到provider中,即使在配置阶段之后,它也将继续处理提供者。您也可以查看此答案以进行澄清。

使用$injector.get('someProvider').$get()将返回一个与instanceCache无关且不是单例的新服务实例。即

$injector.get('someProvider').$get() !== $injector.get('someProvider').$get();

$get背后并没有什么魔力,它只是一个构造函数,注入器并没有办法或理由跟踪它的调用。

对于当前代码,可以安全地使用factory来代替provider。如果必须在config中配置提供程序,那么所有与实例相关的代码都应该转到$get(因为factory只是provider的糖语法,只有$get方法)。