在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; } }; });
configuration:
app.config(function ($routeProvider, dbService) { $routeProvider .when('/', { templateUrl: "partials/editor.html", controller: "AppCtrl", resolve: { data: dbService.getData(), } }) });
但是我得到这个错误:
错误:来自EditorApp的未知提供者:dbService
如何纠正设置并注入此服务?
亚历克斯提供了正确的理由不能做你想做的事情,所以+1。 但是你遇到了这个问题,因为你不能解决它们是如何devise的。
resolve
方法是将服务的string或返回值的函数注入。 既然你在做后者,你需要传递一个实际的函数:
resolve: { data: function (dbService) { return dbService.getData(); } }
当框架去parsingdata
,它会将dbService
注入到函数中,以便您可以自由使用它。 你根本不需要注入config
块来完成这个任务。
好胃口!
将您的服务设置为自定义的AngularJS提供程序
尽pipe接受的答案说,你实际上可以做你打算做的事情,但你需要设置它作为一个可configuration的提供商,以便它在configuration阶段作为服务提供。首先,将您的Service
更改为提供者如下所示。 这里的关键区别在于,在设置defer
的值之后,您将defer.promise
属性设置为由$http.get
返回的promise对象:
提供者服务:(提供者:服务配方)
app.provider('dbService', function dbServiceProvider() { //the provider recipe for services require you specify a $get function this.$get= ['dbhost',function dbServiceFactory(dbhost){ // return the factory as a provider // that is available during the configuration phase return new DbService(dbhost); }] }); 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){ // handle any special stuff here, I would suggest the following: status = 'ok'; status.data = data; }) .error(function(message){ status = 'error'; status.message = message; }) .then(function(){ // now we return an object with data or information about error // for special handling inside your application configuration return status; }) } }
现在,你有一个可configuration的自定义提供程序,你只需要注入它。 这里的主要区别是缺less“注射剂供应商”。
configuration:
app.config(function ($routeProvider) { $routeProvider .when('/', { templateUrl: "partials/editor.html", controller: "AppCtrl", resolve: { dbData: function(DbService, $http) { /* *dbServiceProvider returns a dbService instance to your app whenever * needed, and this instance is setup internally with a promise, * so you don't need to worry about $q and all that */ return DbService('http://dbhost.com').getData(); } } }) });
在你的appCtrl
使用parsing的数据
app.controller('appCtrl',function(dbData, DbService){ $scope.dbData = dbData; // You can also create and use another instance of the dbService here... // to do whatever you programmed it to do, by adding functions inside the // constructor DbService(), the following assumes you added // a rmUser(userObj) function in the factory $scope.removeDbUser = function(user){ DbService.rmUser(user); } })
可能的select
下面的替代方法是类似的方法,但允许定义在.config
发生,将服务封装在应用上下文中的特定模块中。 select适合您的方法。 另请参阅下面的备注和有用的链接,以帮助您掌握所有这些事情
app.config(function($routeProvider, $provide) { $provide.service('dbService',function(){}) //set up your service inside the module's config. $routeProvider .when('/', { templateUrl: "partials/editor.html", controller: "AppCtrl", resolve: { data: } }) });
一些有用的资源
- John Lindquist在egghead.io有一个很棒的5分钟的解释和演示,这是免费的课程之一! 我基本上修改了他的演示,使其在这个请求的上下文中具有特定的
$http
- 查看供应商的AngularJS开发者指南
- 在clevertech.biz也有关于
factory
/service
/provider
的很好的解释。
提供程序通过.service
方法提供了更多的configuration,这使得它更适合作为应用程序级别的提供者,但是您也可以通过在configuration中注入$provide
来像这样将其封装在configuration对象中:
简短的回答:你不能。 AngularJS将不允许你注入服务到configuration中,因为它不能确定它们已经被正确加载了。
看到这个问题和答案: AngularJSdependency injectionmodule.config中的值
模块是在引导过程中应用于应用程序的configuration和运行块的集合。 最简单的forms是模块由两种块的集合组成:
configuration块 – 在提供程序注册和configuration阶段执行。 只有提供者和常量可以注入到configuration块中。 这是为了防止在完全configuration之前意外地实例化服务。
我不认为你应该能够做到这一点,但我已经成功地将一个服务注入config
块。 (AngularJS v1.0.7)
angular.module('dogmaService', []) .factory('dogmaCacheBuster', [ function() { return function(path) { return path + '?_=' + Date.now(); }; } ]); angular.module('touch', [ 'dogmaForm', 'dogmaValidate', 'dogmaPresentation', 'dogmaController', 'dogmaService', ]) .config([ '$routeProvider', 'dogmaCacheBusterProvider', function($routeProvider, cacheBuster) { var bust = cacheBuster.$get[0](); $routeProvider .when('/', { templateUrl: bust('touch/customer'), controller: 'CustomerCtrl' }) .when('/screen2', { templateUrl: bust('touch/screen2'), controller: 'Screen2Ctrl' }) .otherwise({ redirectTo: bust('/') }); } ]); angular.module('dogmaController', []) .controller('CustomerCtrl', [ '$scope', '$http', '$location', 'dogmaCacheBuster', function($scope, $http, $location, cacheBuster) { $scope.submit = function() { $.ajax({ url: cacheBuster('/customers'), //server script to process data type: 'POST', //Ajax events // Form data data: formData, //Options to tell JQuery not to process data or worry about content-type cache: false, contentType: false, processData: false, success: function() { $location .path('/screen2'); $scope.$$phase || $scope.$apply(); } }); }; } ]);
您可以使用$ inject服务在您的config中注入一个服务
的app.config(函数($提供){ $ provide.decorator(“$ exceptionHandler”,function($ delegate,$ injector){ 返回函数(exception,原因){ var $ rootScope = $ injector.get(“$ rootScope”); $ rootScope.addError({message:“Exception”,reason:exception}); $委托(exception,原因); }; }); });
资料来源: http : //odetocode.com/blogs/scott/archive/2014/04/21/better-error-handling-in-angularjs.aspx
使用anuglar.injector从其他模块显式请求服务
只要详细说明kim3er的答案 ,只要它们包含在其他模块中,就可以提供服务,工厂等,而不必将其更改为提供者。
但是,我不确定是否*Provider
(在处理服务或工厂之后通过angular度内部生成)始终可用(可能取决于首先加载的其他内容),因为angular度延迟加载模块。
请注意,如果你想重新注入他们应该被视为常量的值
这是一个更明确,可能更可靠的方式来做到这一点+ 一个工作的重击者
var base = angular.module('myAppBaseModule', []) base.factory('Foo', function() { console.log("Foo"); var Foo = function(name) { this.name = name; }; Foo.prototype.hello = function() { return "Hello from factory instance " + this.name; } return Foo; }) base.service('serviceFoo', function() { this.hello = function() { return "Service says hello"; } return this; }); var app = angular.module('appModule', []); app.config(function($provide) { var base = angular.injector(['myAppBaseModule']); $provide.constant('Foo', base.get('Foo')); $provide.constant('serviceFoo', base.get('serviceFoo')); }); app.controller('appCtrl', function($scope, Foo, serviceFoo) { $scope.appHello = (new Foo("app")).hello(); $scope.serviceHello = serviceFoo.hello(); });
使用$ injector来调用config中的服务方法
我有一个类似的问题,并通过使用$注射器服务解决它,如上所示。 我尝试直接注入服务,但结束了对$ http的循环依赖。 该服务显示错误的模式,我正在使用ui-bootstrap模式,它也依赖于$ https。
$httpProvider.interceptors.push(function($injector) { return { "responseError": function(response) { console.log("Error Response status: " + response.status); if (response.status === 0) { var myService= $injector.get("myService"); myService.showError("An unexpected error occurred. Please refresh the page.") } } }
一个解决scheme很容易做到这一点
注意 :这只适用于asynchronous调用,因为服务在configuration执行时没有被初始化。
你可以使用run()
方法。 例如:
- 您的服务被称为“我的服务”
- 你想使用它在提供程序“MyProvider”上执行asynchronous执行
你的代码:
(function () { //To isolate code TO NEVER HAVE A GLOBAL VARIABLE! //Store your service into an internal variable //It's an internal variable because you have wrapped this code with a (function () { --- })(); var theServiceToInject = null; //Declare your application var myApp = angular.module("MyApplication", []); //Set configuration myApp.config(['MyProvider', function (MyProvider) { MyProvider.callMyMethod(function () { theServiceToInject.methodOnService(); }); }]); //When application is initialized inject your service myApp.run(['MyService', function (MyService) { theServiceToInject = MyService; }]); });
最简单的方法: $injector = angular.element(document.body).injector()
然后用它来运行invoke()
或get()
好吧,我用这个挣了一点,但是我真的做到了。
我不知道由于angular度的变化,答案是否过时,但你可以这样做:
这是你的服务:
.factory('beerRetrievalService', function ($http, $q, $log) { return { getRandomBeer: function() { var deferred = $q.defer(); var beer = {}; $http.post('beer-detail', {}) .then(function(response) { beer.beerDetail = response.data; }, function(err) { $log.error('Error getting random beer', err); deferred.reject({}); }); return deferred.promise; } }; });
这是configuration
.when('/beer-detail', { templateUrl : '/beer-detail', controller : 'productDetailController', resolve: { beer: function(beerRetrievalService) { return beerRetrievalService.getRandomBeer(); } } })