在app.config中注入服务

dnd*_*ndr 168 angularjs

我想在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;
        }
    };
});
Run Code Online (Sandbox Code Playgroud)

配置:

app.config(function ($routeProvider, dbService) {
    $routeProvider
        .when('/',
        {
            templateUrl: "partials/editor.html",
            controller: "AppCtrl",
            resolve: {
                data: dbService.getData(),
            }
        })
});
Run Code Online (Sandbox Code Playgroud)

但我得到这个错误:

错误:未知提供程序:来自EditorApp的dbService

如何纠正设置并注入此服务?

Bri*_*sch 140

将您的服务设置为自定义AngularJS Provider

尽管接受的答案说什么,你居然CAN做什么你打算这样做,但你需要将其设置为一个可配置的提供者,以便它可以作为配置阶段服务.首先,改变你Service的供应商如下所示.这里的关键区别是在设置值之后defer,将defer.promise属性设置为返回的promise对象$http.get:

提供商服务:(提供商:服务配方)

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;
             })
    }    
}
Run Code Online (Sandbox Code Playgroud)

现在,您有一个可配置的自定义提供程序,您只需要注入它.这里的关键区别是缺少"注射剂供应商".

配置:

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();
                }
            }
        })
});
Run Code Online (Sandbox Code Playgroud)

使用你的解决数据 appCtrl

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);
     }

})
Run Code Online (Sandbox Code Playgroud)

可能的替代方案

以下替代方法是类似的方法,但允许定义.config在应用程序上下文中将服务封装到特定模块中.选择适合您的方法.另请参阅下面有关第3个备选和有用链接的说明,以帮助您掌握所有这些内容

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: 
            }
        })
});
Run Code Online (Sandbox Code Playgroud)

一些有用的资源

  • John Lindquist在egghead.io上有一个很好的5分钟解释和演示,这是免费课程之一!我基本上通过$http在此请求的上下文中具体化来修改他的演示
  • 查看提供商的AngularJS开发人员指南
  • 关于factory/ service/ provider clevertech.biz也有一个很好的解释.

提供程序为您提供了更多的.service方法配置,这使它更好地作为应用程序级别提供程序,但您也可以通过注入$provide到配置对象本身来封装它,如下所示:

  • 我认为您在此处提供的信息不正确.您可以使用提供程序,但在配置阶段,您不使用`$ get`调用的结果.相反,你想在提供者实例上添加方法,并在调用`$ get`时返回`this`.实际上在你的例子中你可以使用服务...在提供者中你也不能注入像`$ http`这样的服务.而且这个`//将工厂作为提供者返回,在配置阶段可用'是误导性/不正确的信息 (5认同)
  • 谢谢,我正在寻找这样一个例子; 详细的答案和很棒的链接! (2认同)

Jos*_*ler 130

亚历克斯提供了无法做你想做的事的正确理由,所以+1.但是你遇到了这个问题,因为你并没有完全使用它们如何设计它们.

resolve获取服务的字符串或返回要注入的值的函数.既然你正在做后者,你需要传递一个实际的函数:

resolve: {
  data: function (dbService) {
    return dbService.getData();
  }
}
Run Code Online (Sandbox Code Playgroud)

当框架解决时data,它将注入dbService到函数中,以便您可以自由地使用它.您根本不需要注入config块来完成此任务.

好胃口!

  • 谢谢!但是,如果我这样做,我得到:错误:'undefined'不是服务中的对象(评估'$ q.defer'). (2认同)
  • @BrianVanderbusch我必须承认在你认为我们不同意的地方有些困惑.OP遇到的实际*问题是他将服务注入到配置块中,*无法完成*.解决方案是将服务注入*resolve*.虽然你的答案提供了很多关于服务配置的细节,但我没有看到它与OP遇到的错误有什么关系,你对OP问题的解决方案是*完全相同*:你在解决方案中注入了服务功能和*不*配置功能.你能详细说明我们在这里不同意的地方吗? (2认同)

Ale*_*orn 21

简短的回答:你做不到.AngularJS不允许您将服务注入配置,因为它无法确定它们是否已正确加载.

看到这个问题和答案: AngularJS依赖注入module.config里面的值

模块是配置和运行块的集合,它们在引导过程中应用于应用程序.在最简单的形式中,模块由两种块的集合组成:

配置块 - 在提供程序注册和配置阶段执行.只有提供程序和常量才能注入配置块.这是为了防止在完全配置服务之前意外实例化服务.

  • 实际上,这可以做到.提供答案很快解释. (2认同)

kim*_*3er 5

我认为你不应该这样做,但我已经成功地将一个服务注入了一个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();
                    }
                });
            };
        }
    ]);
Run Code Online (Sandbox Code Playgroud)


005*_*005 5

**使用angular.injector**显式请求来自其他模块的服务**

只是详细说明kim3er的答案,你可以提供服务,工厂等,而不必将它们更改为提供者,只要它们包含在其他模块中......

但是,我不确定*Provider(它是在处理服务或工厂之后由角度内部制作)将始终可用(它可能取决于首先加载的其他内容),因为角度懒惰地加载模块.

请注意,如果要重新注入应将它们视为常量的值.

这是一个更明确,更可靠的方法来做到这一点+ 一个工作的plunker

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();
});
Run Code Online (Sandbox Code Playgroud)


Kor*_*clü 5

您可以使用$ inject服务在配置中注入服务

app.config(function($ provide){

    $ provide.decorator(“ $ exceptionHandler”,function($ delegate,$ injector){
        返回函数(异常,原因){
            var $ rootScope = $ injector.get(“ $ rootScope”);
            $ rootScope.addError({message:“ Exception”,reason:exception});
            $ delegate(异常,原因);
        };
    });

});

资料来源:http : //odetocode.com/blogs/scott/archive/2014/04/21/better-error-handling-in-angularjs.aspx