【问题标题】:AngularJS UI Router using resolved dependency in factory / serviceAngularJS UI Router 在工厂/服务中使用已解析的依赖项
【发布时间】:2015-01-11 19:24:50
【问题描述】:

我有一个这样定义的 UI 路由器(为简单起见进行了修剪):

    $stateProvider
        .state('someState', {
            resolve: {
                model: ['modelService', 'info', function (modelService, info) {
                    return modelService.get(info.id).$promise;
                }]
            },
            controller: 'SomeController'
        });

someState 状态正在使用依赖于model 解析的工厂/服务。它是这样定义的,AngularJS 在此处抛出 Unknown provider: modelProvider 错误:

angular
    .module('someModule')
    .factory('someService', someService);

someService.$inject = ['model'];
function someService(model) { ... }

但是,在此状态的控制器中使用相同的 model 解析工作正常

SomeController.$inject = ['model'];
function SomeController(model) { ... }

所以我了解到 UI 路由器正在延迟 SomeController 的 DI,直到解析发生,这使得 AngularJS 不会抛出错误。但是,当将该解析作为对someService 的依赖时,为什么没有发生同样的延迟?解析仅适用于控制器吗?如果是这种情况,我如何在工厂/服务中使用解析?

【问题讨论】:

  • 您的要求听起来像是一个非常循环的依赖链。服务永远不需要依赖解析,但您可以在解析时将数据绑定回服务

标签: javascript angularjs angular-ui-router


【解决方案1】:

解析仅适用于控制器吗?

是的,仅解决在控制器上的工作。

如果是这样,我如何在工厂/服务中使用解析?

请记住,工厂和服务返回 singleton 对象,即第一次将工厂注入控制器时,它会运行您提供的任何实例化代码并创建一个对象,然后是该工厂的任何后续时间实例化后,返回相同的对象。

换句话说:

angular.module('someModule')
.factory( 'SomeFactory' , function () {
  // this code only runs once
  object = {}
  object.now = Date.now();
  return object
);

SomeFactory.now 将是工厂第一次注入控制器的当前时间,但它不会在后续使用时更新。

因此,对于工厂来说,resolve 的概念并没有真正的意义。如果你想拥有一个动态做某事的服务(这显然很常见),你需要将逻辑放在单例的函数中。

例如,在您提供的代码示例中,您的工厂依赖于模型。一种方法是使用您已经设置的 resolve 方法将模型注入控制器,然后在接受模型并执行您需要做的事情的单例上公开一个方法,如下所示:

angular.module('someModule')
.factory( 'SomeFactory', function () {
  return {
    doSomethingWithModel: function (model) {
      $http.post('wherever', model);
  }
});
.controller('SomeController', function (SomeFactory, model) {
  SomeFactory.doSomethingWithModel(model);
});

或者,如果您根本不需要控制器中的解析值,请不要将其直接放入解析中,而是将解析逻辑放入服务单例上的方法中并在解析中调用该方法,将结果传递给控制器​​。

抽象的对话很难更详细,所以如果您需要进一步的指示,请提供具体的用例。

【讨论】:

  • 谢谢,这是有道理的,当你提醒我工厂/服务是单身的那一刻,我有种“灯泡”的感觉。我不确定我之前是怎么错过那个连接的。
【解决方案2】:

您不能在服务或工厂中使用已解析的值,只能在与已解析值属于同一状态的控制器中使用。服务和工厂是单例的,控制器是新实例化的(在这种情况下)一个状态或任何其他使用 ng-controller 的地方。

实例化发生在 $controller 服务中,该服务能够注入仅属于该控制器的对象。服务和工厂没有这种能力。

【讨论】:

    【解决方案3】:

    您应该查看有关依赖注入的angular docs

    • 服务、指令、过滤器和动画等组件由可注入的工厂方法或构造函数定义。 这些组件可以注入“服务”和“价值”组件作为依赖。
    • 控制器由构造函数定义,可以注入任何“服务”和“值”组件作为依赖项,但也可以为它们提供特殊的依赖项。有关这些特殊依赖项的列表,请参阅下面的控制器。
    • run 方法接受一个函数,该函数可以注入“service”、“value”和“constant”组件作为依赖项。请注意,您不能将“提供者”注入运行块。
    • config 方法接受一个函数,该函数可以注入“provider”和“constant”组件作为依赖项。请注意,您不能将“服务”或“价值”组件注入到配置中。

    因此,每种类型的 Angular 组件都有自己的可接受组件列表来注入。由于服务是单例的,因此将值作为解析的一部分注入确实没有任何意义。如果您的页面上有两个不同的位置使用具有不同解析的服务,则结果将是不确定的。将$scope 注入您的服务没有任何意义。这对控制器来说很有意义,因为控制器负责正在解析的页面的同一区域。

    如果您的someService 需要使用模型中的数据,它应该有一个将数据作为参数的函数,并且您的控制器应该传递它。

    【讨论】:

      猜你喜欢
      • 2014-08-20
      • 1970-01-01
      • 2015-11-10
      • 2014-03-12
      • 1970-01-01
      • 2013-06-11
      • 1970-01-01
      • 2017-11-24
      • 1970-01-01
      相关资源
      最近更新 更多