Внедрить сервис в приложение.конфиг



Я хочу внедрить сервис в приложение.конфигурация, так что данные могут быть получены до вызова контроллера. Я попробовал это так:



сервис:



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


Config:



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


но я получаю эту ошибку:




ошибка: неизвестный поставщик: dbService от EditorApp




Как правильно настроить и внедрить эту услугу?

553   10  

10 ответов:

Алекс предоставил правильную причину для того, чтобы не быть в состоянии сделать то, что вы пытаетесь сделать, так что +1. Но вы сталкиваетесь с этой проблемой, потому что вы не совсем используете решения, как они разработаны.

resolve принимает либо строку Сервиса, либо функцию, возвращающую вводимое значение. Поскольку вы делаете последнее, вам нужно передать фактическую функцию:

resolve: {
  data: function (dbService) {
    return dbService.getData();
  }
}

когда фреймворк переходит к разрешению data, он будет вводить dbService в функцию так что вы можете свободно использовать его. Вам не нужно вводить в config блок вообще для достижения этой цели.

Приятного аппетита!

настройка службы в качестве пользовательского поставщика AngularJS

несмотря на то, что принятый ответ говорит, Вы на самом деле можете сделайте то, что вы намеревались сделать, но вам нужно настроить его как настраиваемый поставщик, чтобы он был доступен как услуга на этапе настройки.. Во-первых, измените свой 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;
             })
    }    
}

теперь у вас есть настраиваемый пользовательский поставщик, вам просто нужно ввести его. Ключевое отличие здесь-отсутствие "поставщика на вашем инъекционном".

config:

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

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

})

Возможны Варианты

следующий альтернативой является аналогичный подход, но позволяет определение происходит в пределах .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: 
            }
        })
});

несколько полезных ресурсов

  • у Джона Линдквиста есть отличное 5-минутное объяснение и демонстрация этого на egghead.io, и это один из бесплатных уроков! Я в основном изменил его демонстрацию, сделав его $http конкретно в контексте этого запроса
  • просмотр руководства разработчика AngularJS на поставщики
  • есть также отличное объяснение о factory/service/provider at clevertech.biz.

поставщик дает вам немного больше конфигурации над .service метод, который делает это лучше как поставщик уровня приложения, но вы также можете инкапсулировать это в самом объекте конфигурации, введя $provide в конфиг вот так:

короткий ответ: вы не можете. AngularJS не позволит вам вводить службы в конфигурацию, потому что он не может быть уверен, что они были загружены правильно.

посмотреть этот вопрос и ответ: инъекция зависимости AngularJS значения внутри модуля.конфигурации

модуль представляет собой набор конфигурационных и запускаемых блоков, которые получают применяется к приложению во время процесса начальной загрузки. В своем простейшая форма модуль состоит из коллекции два вида блоков:

конфигурация блоков - получить выполняется во время регистрации поставщика и фазы конфигурации. Только поставщики и константы смогите быть впрыснуто в блоки конфигурации. Это делается для предотвращения случайное создание экземпляров служб до их полного завершения сконфигурированный.

Я не думаю, что вы должны быть в состоянии сделать это, но я успешно ввел службу в config блок. (В AngularJS В1.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();
                    }
                });
            };
        }
    ]);

** явно запрашивать услуги из других модулей с помощью angular.инжектор **

просто чтобы уточнить 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();
});

вы можете использовать $inject service для внедрения службы в вашу конфигурацию

app.config(function($provide){

    $provide.decorator("$exceptionHandler", function($delegate, $injector){
        return function(exception, cause){
            var $rootScope = $injector.get("$rootScope");
            $rootScope.addError({message:"Exception", reason:exception});
            $delegate(exception, cause);
        };
    });

});

Источник: http://odetocode.com/blogs/scott/archive/2014/04/21/better-error-handling-in-angularjs.aspx

использование $injector для вызова методов службы в конфигурации

У меня была аналогичная проблема, и я решил ее с помощью сервиса $injector, как показано выше. Я попытался ввести службу напрямую, но в итоге получил циклическую зависимость от $http. Служба отображает модальный с ошибкой, и я использую UI-bootstrap modal, который также имеет зависимость от $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.")
            }
        }
    }

решение очень легко сделать

Примечание : это только для вызова asynchrone, потому что служба не инициализируется при выполнении конфигурации.

можно использовать run() метод. Пример :

  1. ваш сервис называется "MyService"
  2. вы хотите использовать его для выполнения asynchrone на провайдере "MyProvider"

код :

(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()

Ну, я немного боролся с этим, но я на самом деле сделал это.

Я не знаю, если ответы уже устарели из-за изменения углового, но вы можете сделать это так:

Это ваш сервис:

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

и это конфиг

.when('/beer-detail', {
  templateUrl : '/beer-detail',
  controller  : 'productDetailController',

  resolve: {
    beer: function(beerRetrievalService) {
      return beerRetrievalService.getRandomBeer();
    }
  }
})

Comments

    Ничего не найдено.