AngularJS UI 路由器在工厂/服务中使用已解析的依赖项
AngularJS UI Router using resolved dependency in factory / service
我有一个 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 <- model <- someService error here:
angular
.module('someModule')
.factory('someService', someService);
someService.$inject = ['model'];
function someService(model) { ... }
但是,在此状态的控制器中使用相同的 model
解析 工作正常:
SomeController.$inject = ['model'];
function SomeController(model) { ... }
所以我了解到 UI 路由器正在延迟 SomeController
的 DI,直到解析发生,这使得 AngularJS 不会抛出错误。但是,当将该解决方案作为对 someService
的依赖时,为什么没有发生相同的延迟?解析是否只适用于控制器?如果是这样,我如何在工厂/服务中使用解析?
您不能在服务或工厂中使用解析值,只能在与解析值属于相同状态的控制器中使用。服务和工厂是单例,并且控制器是为(在这种情况下)一个状态或使用 ng-controller 的任何其他地方新实例化的。
实例化发生在 $controller 服务中,该服务能够注入仅属于该控制器的对象。服务和工厂没有这个能力。
Do resolves only work on controllers?
是的,解决了只能在控制器上工作的问题。
And if that is the case, how can I use a resolve inside a factory / service?
记住工厂和服务 return 单例 对象,即第一次将工厂注入控制器时,它会运行您提供的任何实例化代码并创建一个对象,然后实例化该工厂的任何后续时间,同一个对象被 returned.
换句话说:
angular.module('someModule')
.factory( 'SomeFactory' , function () {
// this code only runs once
object = {}
object.now = Date.now();
return object
);
SomeFactory.now
将是工厂第一次注入控制器的当前时间,但它不会 在后续使用中更新。
因此,工厂解析的概念并没有多大意义。如果你想要一个动态做某事的服务(这显然很常见),你需要将逻辑放在单例上的函数中。
例如,在您提供的代码示例中,您的工厂依赖于一个模型。一种方法是使用您已经设置的 resolve 方法将模型注入控制器,然后在接受模型的单例上公开一个方法并执行您需要做的事情,如下所示:
angular.module('someModule')
.factory( 'SomeFactory', function () {
return {
doSomethingWithModel: function (model) {
$http.post('wherever', model);
}
});
.controller('SomeController', function (SomeFactory, model) {
SomeFactory.doSomethingWithModel(model);
});
或者,如果您根本不需要控制器中的已解析值,请不要将其直接放入解析中,而是将解析逻辑放入服务单例的方法中,然后在解析,将结果传递给控制器。
抽象的对话很难更详细,所以如果您需要进一步的指导,请提供具体的用例。
您应该查看 angular docs 依赖注入:
- 服务、指令、过滤器和动画等组件由可注入的工厂方法或构造函数定义。 这些组件可以通过 "service" 和 "value" 组件 作为依赖项注入。
- 控制器由构造函数定义,可以将任何 "service" 和 "value" 组件作为依赖项注入,但也可以为它们提供特殊依赖项。有关这些特殊依赖项的列表,请参阅下面的控制器。
- 运行方法接受一个函数,该函数可以作为依赖注入"service"、"value"和"constant"组件。请注意,您不能将 "providers" 注入 运行 块。
- config 方法接受一个函数,可以将 "provider" 和 "constant" 组件作为依赖注入。请注意,您不能将 "service" 或 "value" 组件注入配置。
所以每种类型的 angular 组件都有自己的可接受组件列表来注入。由于服务是单例的,因此将值作为解析的一部分注入确实没有任何意义。如果您的页面上有两个不同的地方使用具有不同解析的服务,则结果将是不确定的。这比将 $scope
注入您的服务更有意义。这对控制器有意义,因为控制器负责正在解析的页面的同一区域。
如果您的 someService
需要使用模型中的数据,它应该有一个将数据作为参数的函数,并且您的控制器应该传递它。
我有一个 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 <- model <- someService error here:
angular
.module('someModule')
.factory('someService', someService);
someService.$inject = ['model'];
function someService(model) { ... }
但是,在此状态的控制器中使用相同的 model
解析 工作正常:
SomeController.$inject = ['model'];
function SomeController(model) { ... }
所以我了解到 UI 路由器正在延迟 SomeController
的 DI,直到解析发生,这使得 AngularJS 不会抛出错误。但是,当将该解决方案作为对 someService
的依赖时,为什么没有发生相同的延迟?解析是否只适用于控制器?如果是这样,我如何在工厂/服务中使用解析?
您不能在服务或工厂中使用解析值,只能在与解析值属于相同状态的控制器中使用。服务和工厂是单例,并且控制器是为(在这种情况下)一个状态或使用 ng-controller 的任何其他地方新实例化的。
实例化发生在 $controller 服务中,该服务能够注入仅属于该控制器的对象。服务和工厂没有这个能力。
Do resolves only work on controllers?
是的,解决了只能在控制器上工作的问题。
And if that is the case, how can I use a resolve inside a factory / service?
记住工厂和服务 return 单例 对象,即第一次将工厂注入控制器时,它会运行您提供的任何实例化代码并创建一个对象,然后实例化该工厂的任何后续时间,同一个对象被 returned.
换句话说:
angular.module('someModule')
.factory( 'SomeFactory' , function () {
// this code only runs once
object = {}
object.now = Date.now();
return object
);
SomeFactory.now
将是工厂第一次注入控制器的当前时间,但它不会 在后续使用中更新。
因此,工厂解析的概念并没有多大意义。如果你想要一个动态做某事的服务(这显然很常见),你需要将逻辑放在单例上的函数中。
例如,在您提供的代码示例中,您的工厂依赖于一个模型。一种方法是使用您已经设置的 resolve 方法将模型注入控制器,然后在接受模型的单例上公开一个方法并执行您需要做的事情,如下所示:
angular.module('someModule')
.factory( 'SomeFactory', function () {
return {
doSomethingWithModel: function (model) {
$http.post('wherever', model);
}
});
.controller('SomeController', function (SomeFactory, model) {
SomeFactory.doSomethingWithModel(model);
});
或者,如果您根本不需要控制器中的已解析值,请不要将其直接放入解析中,而是将解析逻辑放入服务单例的方法中,然后在解析,将结果传递给控制器。
抽象的对话很难更详细,所以如果您需要进一步的指导,请提供具体的用例。
您应该查看 angular docs 依赖注入:
- 服务、指令、过滤器和动画等组件由可注入的工厂方法或构造函数定义。 这些组件可以通过 "service" 和 "value" 组件 作为依赖项注入。
- 控制器由构造函数定义,可以将任何 "service" 和 "value" 组件作为依赖项注入,但也可以为它们提供特殊依赖项。有关这些特殊依赖项的列表,请参阅下面的控制器。
- 运行方法接受一个函数,该函数可以作为依赖注入"service"、"value"和"constant"组件。请注意,您不能将 "providers" 注入 运行 块。
- config 方法接受一个函数,可以将 "provider" 和 "constant" 组件作为依赖注入。请注意,您不能将 "service" 或 "value" 组件注入配置。
所以每种类型的 angular 组件都有自己的可接受组件列表来注入。由于服务是单例的,因此将值作为解析的一部分注入确实没有任何意义。如果您的页面上有两个不同的地方使用具有不同解析的服务,则结果将是不确定的。这比将 $scope
注入您的服务更有意义。这对控制器有意义,因为控制器负责正在解析的页面的同一区域。
如果您的 someService
需要使用模型中的数据,它应该有一个将数据作为参数的函数,并且您的控制器应该传递它。