在app.config中注入服务
在app.config中注入服务
我想将一个服务注入到app.config中,以便在调用控制器之前可以检索到数据。我尝试了以下方法:
服务:
app.service('dbService', function() { return { getData: function($q, $http) { var defer = $q.defer(); $http.get('db.php/score/getData').success(function(data) { defer.resolve(data); }); return defer.promise; } }; });
配置:
app.config(function ($routeProvider, dbService) { $routeProvider .when('/', { templateUrl: "partials/editor.html", controller: "AppCtrl", resolve: { data: dbService.getData(), } }) });
但是我得到了这个错误:
错误:未知提供者:EditorApp中的dbService
如何正确设置和注入这个服务?
问题的原因是:AngularJS不允许将服务注入到配置中,因为它无法确保它们已经正确加载。
解决方法是:在配置块中,只能注入提供者和常量,不能注入服务。这是为了防止在服务完全配置之前意外实例化。
所以,事实上是可以做到的。接下来会提供一个解决方法的简短解释。
在上述的问题链接中,有一个解决方法的回答。具体解决方法如下:
1. 创建一个服务,该服务包含需要在配置块中使用的值。
angular.module('myApp').service('myService', function() { this.value = 'example value'; });
2. 在配置块中使用该服务。
angular.module('myApp').config(['myServiceProvider', function(myServiceProvider) { // 使用myServiceProvider的值进行配置 var value = myServiceProvider.value; // 进行其他配置操作 }]);
通过这种方式,我们可以在配置块中使用服务。
问题的原因是在config阶段中,无法直接注入服务。解决方法是将服务设置为可配置的提供者(provider),并在config中注入该提供者。以下是详细步骤:
1. 将服务从普通的Service(服务)转换为Provider(提供者):
app.provider('dbService', function dbServiceProvider() { this.$get= ['dbhost',function dbServiceFactory(dbhost){ return new DbService(dbhost); }] });
2. 在提供者中定义需要的方法和属性:
function DbService(dbhost){ var status; this.setUrl = function(url){ dbhost = url; } this.getData = function($http) { return $http.get(dbhost+'db.php/score/getData') .success(function(data){ status = 'ok'; status.data = data; }) .error(function(message){ status = 'error'; status.message = message; }) .then(function(){ return status; }) } }
3. 在config中注入提供者并使用它:
app.config(function ($routeProvider) { $routeProvider .when('/', { templateUrl: "partials/editor.html", controller: "AppCtrl", resolve: { dbData: function(DbService, $http) { return DbService('http://dbhost.com').getData(); } } }) });
4. 在controller中使用注入的服务:
app.controller('appCtrl',function(dbData, DbService){ $scope.dbData = dbData; $scope.removeDbUser = function(user){ DbService.rmUser(user); } })
这样就可以在config阶段中注入服务,并在controller中使用该服务了。这种方法可以解决在config阶段中无法直接注入服务的问题。
问题:Inject service in app.config的原因是因为在使用resolve时没有按照设计的方式来使用。
解决方法:需要传入一个实际的函数作为参数,而不是传入一个返回值的函数。代码如下:
resolve: { data: function (dbService) { return dbService.getData(); } }
问题:如果按照上述方法处理,会遇到一个错误:“Error: 'undefined' is not an object (evaluating '$q.defer') in the the service.”
解决方法:将注入操作移到传递给`.service`的顶级函数中,将`$q`和`$http`放在那里。
问题:在resolve中,“可以使用服务的字符串或函数”这一说法是正确的。对于函数的使用,你提供了一个很好的示例,非常适用于我。但是对于“服务的字符串”选项,如何将`resolve: {pageData: ['myData', function(myData) {return myData.overview; }] }`简化成`resolve: {pageData: myData.overview}`,以提高清晰度和可读性?
解决方法:在resolve中,字符串实际上是服务的名称,而不是服务上的特定函数。在你的示例中,你可以使用`pageData: 'myData'`,但是你需要从控制器中调用`pageData.overview`。字符串方法可能只在服务工厂返回一个Promise而不是一个API时才有用。所以你目前的方法可能是最好的方式。
问题:这个假设是错误的,即使你的代码没有处理这个服务所需的依赖关系。
解决方法:使用resolve的方式也没有问题,唯一的区别是,使用resolve的方法在解析值之前会先处理成功,而你的方法则将其留给调用者。我更喜欢这个问题中的方法,因为它允许您在将其传递给应用程序的其他部分之前拒绝Promise并进行一些替代处理。我在我的答案中也是这样做的。两种方法都没有错,只是在调用时有不同的步骤。
问题:我对你认为我们不同意的地方感到困惑。问题是,OP遇到的实际问题是他将一个服务注入到了配置块中,这是不可能的。解决方法是将服务注入到resolve中。虽然你的答案提供了关于服务配置的很多细节,但我不明白它与OP遇到的错误有任何关系,你对OP问题的解决方法完全相同:你将服务注入到了resolve函数中,而不是配置函数中。你能详细说明我们在这里的分歧之处吗?
解决方法:使用我展示的方法,可以在状态激活之前配置服务,这样可以在配置阶段抛出/处理错误,可能会改变在应用程序引导之前实例化其他配置值的方式。例如,确定用户的角色以便应用程序编译正确的功能。这种解决方法非常适合在不想在配置/引导阶段运行逻辑,只是在现有服务中进行适配的情况下。感谢分享!
以上是关于“Inject service in app.config”问题的原因和解决方法的整理。