Programming

app.config에 서비스 삽입

procodes 2020. 5. 26. 21:37
반응형

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

설정을 수정하고이 서비스를 주입하는 방법은 무엇입니까?


Alex는 당신이하려는 일을 할 수없는 올바른 이유를 제공했습니다. + 1. 그러나 디자인을 잘 사용하지 않아서이 문제가 발생합니다.

resolve서비스 문자열 또는 주입 할 값을 반환하는 함수를받습니다. 후자를하고 있기 때문에 실제 기능을 전달해야합니다.

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

프레임 워크가 해결 data되면 dbService자유롭게 사용할 수 있도록 함수에 삽입 합니다. 이를 위해 config블록에 전혀 주입 할 필요가 없습니다 .

많이 드세요!


서비스를 사용자 정의 AngularJS 제공자로 설정

허용 대답의 말씀에도 불구하고, 당신은 실제로 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;
             })
    }    
}

이제 구성 가능한 사용자 지정 공급자가 있으므로 주입하기 만하면됩니다. 여기서 중요한 차이점은 누락 된 "주사기에 제공자"라는 점입니다.

구성 :

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하도록하여 앱 컨텍스트에서 특정 모듈 내로 서비스를 캡슐화합니다. 자신에게 맞는 방법을 선택하십시오. 또한 이러한 모든 것들을 익히는 데 도움이되는 세 번째 대안 및 유용한 링크에 대한 메모는 아래를 참조하십시오.

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 개발자 안내서보기
  • 대한 훌륭한 설명도있다 factory/ service/ provider clevertech.biz에서가 .

프로 바이더는 .service메소드에 대해 약간 더 많은 구성을 제공하여 애플리케이션 레벨 프로 바이더로서 더 나아지지만 다음 $provide과 같이 구성 에 주입하여 구성 오브젝트 자체 내에이를 캡슐화 할 수도 있습니다 .


짧은 대답 : 당신은 할 수 없습니다. AngularJS는 서비스가 올바르게로드되었는지 확인할 수 없으므로 구성에 서비스를 주입 할 수 없습니다.

이 질문과 답변을보십시오 : module.config 내부의 AngularJS 의존성 주입

모듈은 부트 스트랩 프로세스 동안 응용 프로그램에 적용되는 구성 및 실행 블록 모음입니다. 가장 간단한 형태로 모듈은 두 종류의 블록으로 구성됩니다.

구성 블록 -공급자 등록 및 구성 단계에서 실행됩니다. 공급자와 상수 만 구성 블록에 주입 할 수 있습니다. 이는 서비스가 완전히 구성되기 전에 실수로 서비스가 인스턴스화되는 것을 방지하기위한 것입니다.


나는 당신이 이것을 할 수 있다고 생각하지 않지만 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 service를 사용하여 구성에 서비스를 주입 할 수 있습니다

app.config (function ($ provide) {

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

});

Source: http://odetocode.com/blogs/scott/archive/2014/04/21/better-error-handling-in-angularjs.aspx


** Explicitly request services from other modules using angular.injector **

Just to elaborate on kim3er's answer, you can provide services, factories, etc without changing them to providers, as long as they are included in other modules...

However, I'm not sure if the *Provider (which is made internally by angular after it processes a service, or factory) will always be available (it may depend on what else loaded first), as angular lazily loads modules.

Note that if you want to re-inject the values that they should be treated as constants.

Here's a more explicit, and probably more reliable way to do it + a working 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();
});

Using $injector to call service methods in config

I had a similar issue and resolved it by using the $injector service as shown above. I tried injecting the service directly but ended up with a circular dependency on $http. The service displays a modal with the error and I am using ui-bootstrap modal which also has a dependency on $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.")
            }
        }
    }

A solution very easy to do it

Note : it's only for an asynchrone call, because service isn't initialized on config execution.

You can use run() method. Example :

  1. Your service is called "MyService"
  2. You want to use it for an asynchrone execution on a provider "MyProvider"

Your code :

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

Well, I struggled a little with this one, but I actually did it.

I don't know if the answers are outdated because of some change in angular, but you can do it this way:

This is your service:

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

And this is the config

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

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

Easiest way: $injector = angular.element(document.body).injector()

Then use that to run invoke() or get()

참고URL : https://stackoverflow.com/questions/15937267/inject-service-in-app-config

반응형