programing

약속을 돌려주는 각진 공장

mytipbox 2023. 3. 19. 17:47
반응형

약속을 돌려주는 각진 공장

앱이 시작되면 서버에서 설정을 로드합니다.대부분의 컨트롤러는 유용한 작업을 수행하기 전에 이 기능을 필요로 합니다.컨트롤러의 코드를 가능한 한 간단하게 하고 싶습니다.내 시도는 실패했지만, 다음과 같다.

app.factory('settings', ['$rootScope', '$http', '$q', function($rootScope, $http, $q) {
    var deferred = $q.defer();

    $http.get('/api/public/settings/get').success(function(data) {
        $rootScope.settings = data;
        deferred.resolve();
    });

    return deferred.promise;
}]);

app.controller('SomeCtrl', ['$rootScope', 'settings', function($rootScope, settings) {
    // Here I want settings to be available
}]);

설정이 많은 것은 피하고 싶다.그러면 (function()...

어떻게 하면 이 문제를 잘 해결할 수 있을까?

$http 자체는 $q 안에 바인드할 필요가 없다는 약속을 반환합니다.이것은 좋은 프랙티스가 아니고, Anti Pattern으로 간주됩니다.

용도:-

    app.factory('settings', ['$rootScope', '$http', '$q', function($rootScope, $http) {
        return $http.get('/api/public/settings/get')
    }]);

    app.controller('SomeCtrl', ['settings',$scope, function(settings,$scope) {
        settings.then(function(result){
                $scope.settings=result.data;
          });
    }]);

방법은 다음과 같습니다.

app.factory('settings', ['$rootScope', '$http', '$q', function($rootScope, $http, $q) {
    var deferred = $q.defer();

    $http.get('/api/public/settings/get').success(function(data) {
        deferred.resolve(data);
    });

    return deferred.promise;
}]);

app.controller('SomeCtrl', ['$scope', 'settings', function($scope, settings) {
    settings.then(function(data){
          $scope.settings=data;
       })
}]);

$rootScope의 변경에 $watch를 사용해야 하는 경우 $rootScope를 오버로드하지 마십시오(권장되지 않음).

"기다려야 할 곳"입니다.

Angular에 내장되어 있는 유일한 방법은 컨트롤러가 비동기 데이터를 로드하기 위해 스스로 대기하는 것을 완전히 배제하는 것입니다.$routeProvider의 루트resolve재산(또는 대체품)$stateProviderui.router모든 약속이 해결되고 해결된 데이터가 삽입될 때만 컨트롤러가 실행됩니다.

그래서, ng-route 대안 - plunker:

$routeProvider.when("/", {
   controller: "SomeCtrl",
   templateUrl: "someTemplate.html",
   resolve: {
     settings: function(settingsSvc){
       return settingsSvc.load(); // I renamed the loading function for clarity
     }
   });

그럼, 인SomeCtrl추가할 수 있습니다.settings주입 가능한 의존관계로서:

.controller("SomeCtrl", function($scope, settings){
   if (settings.foo) $scope.bar = "foo is on";
})

로딩할 때까지 "대기"someTemplate<div ng-view></div>설정이 해결될 때까지.

settingsSvc는 HTTP 요청을 다시 실행할 필요가 없도록 약속을 캐시해야 합니다.주의: 다른 답변에서 언급한 바와 같이,$q.defer사용하고 있는 API가$http)는 이미 약속을 반환합니다.

.factory("settingsSvc", function($http){
   var svc = {settings: {}};
   var promise = $http.get('/api/public/settings/get').success(function(data){
      svc.settings = data; // optionally set the settings data here
   });
   svc.load = function(){
      return promise;
   }
   return svc;
});

다른 접근법이 마음에 들지 않으면ngRoute그 방법, 예를 들어,settings서비스 브로드캐스트$rootScope설정이 로드되고 컨트롤러가 이에 반응하여 모든 작업을 수행할 수 있는 이벤트입니다.하지만 그게 더 '무거운' 것 같아.then.

번째 방법인 plunker는 모든 종속성이 미리 로드되어 있을 때만 앱 수준의 컨트롤러를 "활성화"하는 이라고 생각합니다.

.controller("AppCtrl", function($q, settingsSvc, someOtherService){
   $scope.loaded = false;
   $q.all([settingsSvc.load, someOtherService.prefetch]).then(function(){
      $scope.loaded = true;
   });
});

[보기(View)]그래서,ng-if와 함께loaded:

<body ng-controller="AppCtrl">
  <div ng-if="!loaded">loading app...</div>

  <div ng-if="loaded">
    <div ng-controller="MainCtrl"></div>
    <div ng-controller="MenuCtrl"></div>
  </div>
</body>

최소 이 정의의 애플리케이션 루트 상태를 가지면 이 작업을 쉽게 수행할 수 있습니다.

$stateProvider
    .state('app', {
        abstract: true,
        template: '<div ui-view></div>'
        resolve:     {
            settings:  function($http){
                return $http.get('/api/public/settings/get')
                            .then(function(response) {return response.data});
            }
        }
    })

그 후 모든 응용 프로그램 상태를 이 루트 상태에서 상속할 수 있습니다.

  1. 모든 컨트롤러는 설정이 로드된 후에만 실행됩니다.
  2. 모든 컨트롤러는 가능한 한 주입 가능한 설정으로 해결된 값에 액세스할 수 있습니다.

전술한 바와 같이 해결은 원래 ng-route에서도 기능하지만 네스트를 지원하지 않기 때문에 이 접근법은 ui-router만큼 유용하지 않습니다.

설정이 로드된 후 애플리케이션을 수동으로 부트스트랩할 수 있습니다.

var initInjector = angular.injector(["ng"]);
var $http = initInjector.get("$http");
var $rootScope = initInjector.get("$rootScope");

$http.get('/api/public/settings/get').success(function(data) {
    $rootScope.settings = data;
    angular.element(document).ready(function () {
        angular.bootstrap(document, ["app"]);
    });
});

이 경우 설정이 로드된 후에만 전체 응용 프로그램이 실행됩니다.

자세한 내용은 각도 부트스트랩 설명서를 참조하십시오.

언급URL : https://stackoverflow.com/questions/28830003/angular-factory-returning-a-promise

반응형