AngularJS : 비동기 데이터로 서비스 초기화


475

비동기 데이터로 초기화하려는 AngularJS 서비스가 있습니다. 이 같은:

myModule.service('MyService', function($http) {
    var myData = null;

    $http.get('data.json').success(function (data) {
        myData = data;
    });

    return {
        setData: function (data) {
            myData = data;
        },
        doStuff: function () {
            return myData.getSomeData();
        }
    };
});

무언가 가 돌아 doStuff()오기 전에 전화를 걸면 myDatanull 포인터 예외가 발생 하기 때문에 분명히 작동하지 않습니다 . 여기여기에 묻는 다른 질문 중 일부를 읽을 수 있는 한 몇 가지 옵션이 있지만 그중 어느 것도 매우 깨끗한 것처럼 보이지 않습니다 (아마도 뭔가 빠진 것 같습니다).

"실행"설정 서비스

내 앱을 설정할 때 다음을 수행하십시오.

myApp.run(function ($http, MyService) {
    $http.get('data.json').success(function (data) {
        MyService.setData(data);
    });
});

그런 다음 내 서비스는 다음과 같습니다.

myModule.service('MyService', function() {
    var myData = null;
    return {
        setData: function (data) {
            myData = data;
        },
        doStuff: function () {
            return myData.getSomeData();
        }
    };
});

이것은 약간의 시간 동안 작동하지만 모든 것이 초기화되는 데 걸리는 시간보다 비동기 데이터가 오래 걸리면 호출 할 때 null 포인터 예외가 발생합니다. doStuff()

약속 객체 사용

아마도 효과가있을 것입니다. 내가 MyService를 호출하는 모든 곳에서 유일한 단점은 doStuff ()가 약속을 반환하고 모든 코드가 약속과 then상호 작용 해야한다는 것을 알아야합니다 . 오히려 내 응용 프로그램을로드하기 전에 myData가 돌아올 때까지 기다리십시오.

수동 부트 스트랩

angular.element(document).ready(function() {
    $.getJSON("data.json", function (data) {
       // can't initialize the data here because the service doesn't exist yet
       angular.bootstrap(document);
       // too late to initialize here because something may have already
       // tried to call doStuff() and would have got a null pointer exception
    });
});

전역 자바 스크립트 Var 내 JSON을 전역 자바 스크립트 변수로 직접 보낼 수 있습니다.

HTML :

<script type="text/javascript" src="data.js"></script>

data.js :

var dataForMyService = { 
// myData here
};

그런 다음 초기화 할 때 사용할 수 있습니다 MyService.

myModule.service('MyService', function() {
    var myData = dataForMyService;
    return {
        doStuff: function () {
            return myData.getSomeData();
        }
    };
});

이것도 작동하지만 냄새가 나는 전역 자바 스크립트 변수가 있습니다.

이것들은 나의 유일한 옵션입니까? 이러한 옵션 중 하나가 다른 옵션보다 낫습니까? 나는 이것이 꽤 긴 질문이라는 것을 알고 있지만 모든 옵션을 탐색하려고 노력하고 있음을 보여주고 싶었습니다. 어떤 지침이라도 대단히 감사하겠습니다.


앵귤러-부트 스트랩 은 코드를 통해 비동기 적으로 코드를 통해 서버에서 데이터를 가져온 $http다음 서비스에 데이터를 저장 한 다음 앱을 부트 스트랩합니다.
Steven Wexler

답변:


327

봤어 $routeProvider.when('/path',{ resolve:{...}? 그것은 약속 접근법을 조금 더 깨끗하게 만들 수 있습니다.

당신의 봉사에 약속을 나타내십시오 :

app.service('MyService', function($http) {
    var myData = null;

    var promise = $http.get('data.json').success(function (data) {
      myData = data;
    });

    return {
      promise:promise,
      setData: function (data) {
          myData = data;
      },
      doStuff: function () {
          return myData;//.getSomeData();
      }
    };
});

resolve경로 설정에 추가 하십시오 :

app.config(function($routeProvider){
  $routeProvider
    .when('/',{controller:'MainCtrl',
    template:'<div>From MyService:<pre>{{data | json}}</pre></div>',
    resolve:{
      'MyServiceData':function(MyService){
        // MyServiceData will also be injectable in your controller, if you don't want this you could create a new promise with the $q service
        return MyService.promise;
      }
    }})
  }):

모든 종속성이 해결되기 전에 컨트롤러가 인스턴스화되지 않습니다.

app.controller('MainCtrl', function($scope,MyService) {
  console.log('Promise is now resolved: '+MyService.doStuff().data)
  $scope.data = MyService.doStuff();
});

plnkr에서 예제를 만들었습니다 : http://plnkr.co/edit/GKg21XH0RwCMEQGUdZKH?p=preview


1
답변 주셔서 감사합니다! MyService를 사용하는 리졸 브 맵에 아직 서비스가 없다면 그것은 나를 위해 일할 것입니다. 내 상황으로 pplunker를 업데이트했습니다 : plnkr.co/edit/465Cupaf5mtxljCl5NuF?p=preview . MyOtherService가 MyService가 초기화 될 때까지 기다리는 방법이 있습니까?
testing123

2
나는 MyOtherService에서 약속을 묶을 것이라고 생각합니다. 플 링커를 체인과 일부 의견으로 업데이트했습니다. 어떻게 보입니까? plnkr.co/edit/Z7dWVNA9P44Q72sLiPjW?p= 미리보기
joakimbl

3
지시어와 다른 컨트롤러 ($ routeProvider와 함께 사용하는 컨트롤러가 기본, 보조 탐색 항목을 처리하고 있습니다. 즉 'MyOtherService'입니다. '가 해결되었습니다. 나는 내가 가지고있는 성공으로 이것을 계속 시도하고 업데이트 할 것입니다. 컨트롤러와 지시문을 초기화하기 전에 데이터가 반환 될 때까지 기다릴 수있는 각도에 고리가 있기를 바랍니다. 도와 주셔서 감사합니다. 모든 것을 감싸는 메인 컨트롤러가 있다면 이것이 효과가 있었을 것입니다.
testing123

43
여기서 resolve언급되지 않은 컨트롤러에 속성을 할당하는 방법에 대한 질문 입니다 $routeProvider. 예를 들면 다음과 같습니다 <div ng-controller="IndexCtrl"></div>. 여기서는 컨트롤러를 명시 적으로 언급하고 라우팅을 통해로드하지 않습니다. 이 경우 컨트롤러의 인스턴스화를 어떻게 지연시킬 수 있습니까?
callmekatootie

19
음 라우팅을 사용하지 않으면 어떻게 될까요? 이것은 라우팅을 사용하지 않으면 비동기 데이터로 각도 앱을 작성할 수 없다는 것과 거의 같습니다. 앱에 데이터를 가져 오는 데 권장되는 방법은 비동기식으로 데이터를로드하는 것입니다. 그러나 컨트롤러가 둘 이상 있고 서비스를 시작하자마자 BOOM은 불가능합니다.
wired_in

88

Martin Atkins의 솔루션을 기반으로 한 완벽하고 간결한 순수 각도 솔루션은 다음과 같습니다.

(function() {
  var initInjector = angular.injector(['ng']);
  var $http = initInjector.get('$http');
  $http.get('/config.json').then(
    function (response) {
      angular.module('config', []).constant('CONFIG', response.data);

      angular.element(document).ready(function() {
          angular.bootstrap(document, ['myApp']);
        });
    }
  );
})();

이 솔루션은 자체 실행 익명 함수를 사용하여 $ http 서비스를 가져오고 구성을 요청하며 사용 가능 해지면 CONFIG라는 상수에 삽입합니다.

완전히 완료되면 문서가 준비 될 때까지 기다린 다음 Angular 앱을 부트 스트랩합니다.

이것은 Martin의 솔루션에 비해 약간 개선 된 것으로 문서 준비가 완료 될 때까지 구성 가져 오기를 연기했습니다. 내가 아는 한, $ http 호출을 지연시킬 이유가 없습니다.

단위 테스트

참고 : 코드에 app.js파일 이 포함되어있을 때 단위 테스트 할 때이 솔루션이 제대로 작동하지 않는다는 것을 알았습니다 . 그 이유는 JS 파일이로드 될 때 위 코드가 즉시 실행되기 때문입니다. 이것은 테스트 프레임 워크 (제 경우에는 Jasmine)가의 모의 구현을 제공 할 기회가 없다는 것을 의미합니다 $http.

내가 완전히 만족하지 않는 솔루션은이 코드를 index.html파일 로 옮기는 것이 었 으므로 Grunt / Karma / Jasmine 단위 테스트 인프라에서 볼 수 없었습니다.


1
'글로벌 범위를 오염시키지 마십시오'와 같은 규칙은 코드를 개선하는 정도 (복잡성, 유지 관리 성, 보안 성 등)에만 따라야합니다. 단순히 단일 전역 변수에 데이터를로드하는 것 보다이 솔루션이 어떻게 더 나은지 알 수 없습니다. 내가 무엇을 놓치고 있습니까?
david004

4
Angular의 의존성 주입 시스템을 사용하여 필요한 모듈에서 'CONFIG'상수에 액세스 할 수는 있지만 그렇지 않은 다른 모듈을 방해 할 위험은 없습니다. 예를 들어 전역 'config'변수를 사용한 경우 다른 타사 코드에서도 같은 변수를 찾을 수 있습니다.
JBCP

1
나는 앵귤러 초보자입니다. 다음은 내 앱에서 구성 모듈 종속성을 어떻게 해결했는지에 대한 참고 사항입니다. gist.github.com/dsulli99/0be3e80db9b21ce7b989 ref : tutorials.jenkov.com/angularjs/… 이 솔루션에 감사드립니다.
dps

7
아래의 다른 수동 부트 스트랩 솔루션 중 하나에 주석에 언급되어 있지만 그것을 발견하지 못한 각도 초보자로서 제대로 작동하려면 html 코드에서 ng-app 지시문을 삭제해야한다고 지적 할 수 있습니다 -ng-app를 통해 자동 부트 스트랩을이 수동 방법으로 대체합니다. ng-app를 꺼내지 않으면 응용 프로그램이 실제로 작동하지만 콘솔에 알 수없는 다양한 공급자 오류가 표시됩니다.
IrishDubGuy

49

@XMLilley가 설명한 것과 비슷한 접근 방식을 사용했지만 $http구성을로드하고 낮은 수준의 API 또는 jQuery를 사용하지 않고 추가 초기화를 수행하는 것과 같은 AngularJS 서비스를 사용할 수있는 기능을 원했습니다 .

블록 resolve에서조차 앱을 시작할 때 상수로 사용할 수있는 값이 필요했기 때문에 경로에서 사용 하는 것도 옵션이 아닙니다 module.config().

구성을로드하고 실제 앱에서 상수로 설정하고 부트 스트랩하는 작은 AngularJS 앱을 만들었습니다.

// define the module of your app
angular.module('MyApp', []);

// define the module of the bootstrap app
var bootstrapModule = angular.module('bootstrapModule', []);

// the bootstrapper service loads the config and bootstraps the specified app
bootstrapModule.factory('bootstrapper', function ($http, $log, $q) {
  return {
    bootstrap: function (appName) {
      var deferred = $q.defer();

      $http.get('/some/url')
        .success(function (config) {
          // set all returned values as constants on the app...
          var myApp = angular.module(appName);
          angular.forEach(config, function(value, key){
            myApp.constant(key, value);
          });
          // ...and bootstrap the actual app.
          angular.bootstrap(document, [appName]);
          deferred.resolve();
        })
        .error(function () {
          $log.warn('Could not initialize application, configuration could not be loaded.');
          deferred.reject();
        });

      return deferred.promise;
    }
  };
});

// create a div which is used as the root of the bootstrap app
var appContainer = document.createElement('div');

// in run() function you can now use the bootstrapper service and shutdown the bootstrapping app after initialization of your actual app
bootstrapModule.run(function (bootstrapper) {

  bootstrapper.bootstrap('MyApp').then(function () {
    // removing the container will destroy the bootstrap app
    appContainer.remove();
  });

});

// make sure the DOM is fully loaded before bootstrapping.
angular.element(document).ready(function() {
  angular.bootstrap(appContainer, ['bootstrapModule']);
});

http://plnkr.co/edit/FYznxP3xe8dxzwxs37hi?p=preview 에서 실제로 사용하십시오 ( $timeout대신 사용 $http).

최신 정보

Martin Atkins와 JBCP가 아래에 설명하는 접근 방식을 사용하는 것이 좋습니다.

업데이트 2

여러 프로젝트에서 필요했기 때문에 방금 이것을 처리하는 bower 모듈을 출시했습니다. https://github.com/philippd/angular-deferred-bootstrap

백엔드에서 데이터를로드하고 AngularJS 모듈에서 APP_CONFIG라는 상수를 설정하는 예제 :

deferredBootstrapper.bootstrap({
  element: document.body,
  module: 'MyApp',
  resolve: {
    APP_CONFIG: function ($http) {
      return $http.get('/api/demo-config');
    }
  }
});

11
deferredBootstrapper는 갈 길입니다
fatlinesofcode

44

"수동 부트 스트랩"사례는 부트 스트랩 전에 인젝터를 수동으로 작성하여 Angular 서비스에 액세스 할 수 있습니다. 이 초기 인젝터는 독립형이며 (요소에 부착되지 않음)로드 된 모듈의 서브 세트 만 포함합니다. 필요한 모든 핵심 Angular 서비스라면 다음 ng과 같이 로드하는 것으로 충분합니다 .

angular.element(document).ready(
    function() {
        var initInjector = angular.injector(['ng']);
        var $http = initInjector.get('$http');
        $http.get('/config.json').then(
            function (response) {
               var config = response.data;
               // Add additional services/constants/variables to your app,
               // and then finally bootstrap it:
               angular.bootstrap(document, ['myApp']);
            }
        );
    }
);

예를 들어, module.constant메커니즘을 사용 하여 앱에서 데이터를 사용할 수있게 만들 수 있습니다.

myApp.constant('myAppConfig', data);

이것은 myAppConfig이제 다른 모든 서비스처럼 주입, 특히이 구성 단계에서 사용할 수 할 수 있습니다 :

myApp.config(
    function (myAppConfig, someService) {
        someService.config(myAppConfig.someServiceConfig);
    }
);

또는 더 작은 응용 프로그램의 경우 응용 프로그램 전체에 구성 형식에 대한 지식을 확산시키지 않으면 서 전역 구성을 서비스에 직접 주입 할 수 있습니다.

물론 여기서 비동기 작업을 수행하면 응용 프로그램의 부트 스트랩이 차단되어 템플릿의 컴파일 / 링크 ng-cloak가 차단되므로 구문 분석되지 않은 템플릿이 작업 중에 표시되지 않도록 지시문을 사용하는 것이 좋습니다 . AngularJS가 초기화 될 때까지만 표시되는 HTML을 제공하여 DOM에 일종의 로딩 표시를 제공 할 수도 있습니다.

<div ng-if="initialLoad">
    <!-- initialLoad never gets set, so this div vanishes as soon as Angular is done compiling -->
    <p>Loading the app.....</p>
</div>
<div ng-cloak>
    <!-- ng-cloak attribute is removed once the app is done bootstrapping -->
    <p>Done loading the app!</p>
</div>

Plunker 에서이 접근법 의 완전한 작동 예제 를 작성 하여 정적 JSON 파일에서 구성을 예로로드했습니다.


문서가 준비 될 때까지 $ http.get ()을 연기해야한다고 생각하지 않습니다.
JBCP

@ JBCP 예, HTTP 응답이 반환 될 때까지 문서가 준비 될 때까지 기다리지 않도록 이벤트를 바꾸면 잘 작동한다는 것이 맞습니다 .HTTP를 시작할 수 있다는 이점이 있습니다. 더 빨리 요청하십시오. DOM이 준비 될 때까지 부트 스트랩 호출 만 기다려야합니다.
Martin Atkins

2
나는 당신의 접근 방식으로 bower 모듈을 만들었습니다 : github.com/philippd/angular-deferred-bootstrap
philippd March

@ MartinAtkins, 방금 귀하의 훌륭한 접근 방식이 Angular v1.1 이상에서 작동하지 않는 것으로 나타났습니다. Angular의 초기 버전은 응용 프로그램이 부트 스트랩 될 때까지 "그런 다음"을 이해하지 못하는 것처럼 보입니다. 당신의 쿵하는 소리에 그것을 보는 것은으로 각도 URL을 대체 code.angularjs.org/1.1.5/angular.min.js
vkelman

16

나는 같은 문제가 있었다 : 나는 resolve물건을 좋아 하지만 ng-view의 내용에서만 작동합니다. ng-view 외부에 존재하고 라우팅이 시작되기 전에 데이터로 초기화 해야하는 컨트롤러 (최상위 탐색 용)가 있다면 어떻게됩니까? 서버 측에서 어떻게 작동하는지 막기 위해 어떻게해야합니까?

수동 부트 스트랩과 각도 상수를 사용하십시오 . 기본 XHR은 데이터를 가져오고 콜백에서 각도를 부트 스트랩하여 비동기 문제를 처리합니다. 아래 예에서는 전역 변수를 만들 필요조차 없습니다. 반환 된 데이터는 주사 가능한 각도 범위에만 존재하며, 주입하지 않는 한 컨트롤러, 서비스 등에도 존재하지 않습니다. ( resolve라우팅 된 뷰를 위해 객체 의 출력을 컨트롤러에 주입하는 것과 같이) 서비스로 해당 데이터와 상호 작용하려는 경우 서비스를 생성하고 데이터를 주입하면 아무도 더 현명하지 않습니다. .

예:

//First, we have to create the angular module, because all the other JS files are going to load while we're getting data and bootstrapping, and they need to be able to attach to it.
var MyApp = angular.module('MyApp', ['dependency1', 'dependency2']);

// Use angular's version of document.ready() just to make extra-sure DOM is fully 
// loaded before you bootstrap. This is probably optional, given that the async 
// data call will probably take significantly longer than DOM load. YMMV.
// Has the added virtue of keeping your XHR junk out of global scope. 
angular.element(document).ready(function() {

    //first, we create the callback that will fire after the data is down
    function xhrCallback() {
        var myData = this.responseText; // the XHR output

        // here's where we attach a constant containing the API data to our app 
        // module. Don't forget to parse JSON, which `$http` normally does for you.
        MyApp.constant('NavData', JSON.parse(myData));

        // now, perform any other final configuration of your angular module.
        MyApp.config(['$routeProvider', function ($routeProvider) {
            $routeProvider
              .when('/someroute', {configs})
              .otherwise({redirectTo: '/someroute'});
          }]);

        // And last, bootstrap the app. Be sure to remove `ng-app` from your index.html.
        angular.bootstrap(document, ['NYSP']);
    };

    //here, the basic mechanics of the XHR, which you can customize.
    var oReq = new XMLHttpRequest();
    oReq.onload = xhrCallback;
    oReq.open("get", "/api/overview", true); // your specific API URL
    oReq.send();
})

이제 NavData상수가 존재합니다. 계속해서 컨트롤러 또는 서비스에 주입하십시오.

angular.module('MyApp')
    .controller('NavCtrl', ['NavData', function (NavData) {
        $scope.localObject = NavData; //now it's addressable in your templates 
}]);

물론 베어 XHR 객체를 사용하면 $httpJQuery가 처리 할 수 있는 많은 장점을 제거 할 수 있지만이 예제는 최소한 간단한 의존성을 위해 특별한 종속성없이 작동합니다 get. 요청에 대해 더 많은 권한을 원할 경우 외부 라이브러리를로드하여 도움을 받으십시오. 그러나이 $http맥락에서 각도 또는 다른 도구에 액세스하는 것이 가능하지 않다고 생각합니다 .

(SO 관련 게시물 )


8

당신이 할 수있는 일은 앱의 .config에서 경로에 대한 resolve 객체를 만들고 $ q (promise object)에 함수 패스와 의존하는 서비스 이름을 만들고, 약속을 해결하는 것입니다. 서비스에서 $ http에 대한 콜백 함수는 다음과 같습니다.

루트 구성

app.config(function($routeProvider){
    $routeProvider
     .when('/',{
          templateUrl: 'home.html',
          controller: 'homeCtrl',
          resolve:function($q,MyService) {
                //create the defer variable and pass it to our service
                var defer = $q.defer();
                MyService.fetchData(defer);
                //this will only return when the promise
                //has been resolved. MyService is going to
                //do that for us
                return defer.promise;
          }
      })
}

Angular는 defer.resolve ()가 호출 될 때까지 템플릿을 렌더링하거나 컨트롤러를 사용할 수 없게합니다. 우리는 우리의 봉사에서 그렇게 할 수 있습니다.

서비스

app.service('MyService',function($http){
       var MyService = {};
       //our service accepts a promise object which 
       //it will resolve on behalf of the calling function
       MyService.fetchData = function(q) {
             $http({method:'GET',url:'data.php'}).success(function(data){
                 MyService.data = data;
                 //when the following is called it will
                 //release the calling function. in this
                 //case it's the resolve function in our
                 //route config
                 q.resolve();
             }
       }

       return MyService;
});

이제 MyService에 데이터 속성에 할당 된 데이터가 있고 경로 확인 객체의 약속이 해결되었으며 경로에 대한 컨트롤러가 실제로 작동하며 서비스의 데이터를 컨트롤러 객체에 할당 할 수 있습니다.

제어 장치

  app.controller('homeCtrl',function($scope,MyService){
       $scope.servicedata = MyService.data;
  });

이제 컨트롤러 범위의 모든 바인딩은 MyService에서 시작된 데이터를 사용할 수 있습니다.


시간이 더 있으면이 기회를 드리겠습니다. 이것은 다른 사람들이 ngModules에서하려고했던 것과 유사합니다.
testing123

1
나는이 접근법을 좋아하고 이전에 사용했지만 현재 여러 경로가있을 때 깨끗한 방법 으로이 작업을 수행하는 방법을 찾으려고합니다. 각 경로는 프리 페치 된 데이터에 의존하거나 의존하지 않을 수 있습니다. 그것에 대한 생각?
ivarni

btw, 프리 페치 된 데이터가 필요한 각 서비스가 초기화 될 때 요청을하고 약속을 반환 한 다음 다른 경로에 필요한 서비스로 resolve-objects를 설정하려고합니다. 나는 덜 장황한 방법이 있었으면 좋겠다.
ivarni 2016 년

1
@dewd 그것이 내가 목표로 한 것이지만, 해결 블록을 반복하지 않고 "어떤 경로가로드되는지에 관계없이 먼저이 모든 것을 가져 오십시오"라고 말하는 방법이 있다면 훨씬 선호합니다. 그들 모두는 그들이 의존하는 것을 가지고 있습니다. 그러나 그것은 큰 거래가 아닙니다. 조금 더 건조한 느낌이들 것입니다. :)
ivarni

2
이것은 내가 resolve속성이있는 객체 를 만들어야 하는 것을 제외하고는 내가 끝내는 경로 입니다. 그래서 그것은 끝났다resolve:{ dataFetch: function(){ // call function here } }
aron.duby

5

그래서 해결책을 찾았습니다. angularJS 서비스를 만들었습니다. MyDataRepository라고 부르고이를위한 모듈을 만들었습니다. 그런 다음 서버 측 컨트롤러에서이 JavaScript 파일을 제공합니다.

HTML :

<script src="path/myData.js"></script>

서버 측:

@RequestMapping(value="path/myData.js", method=RequestMethod.GET)
public ResponseEntity<String> getMyDataRepositoryJS()
{
    // Populate data that I need into a Map
    Map<String, String> myData = new HashMap<String,String>();
    ...
    // Use Jackson to convert it to JSON
    ObjectMapper mapper = new ObjectMapper();
    String myDataStr = mapper.writeValueAsString(myData);

    // Then create a String that is my javascript file
    String myJS = "'use strict';" +
    "(function() {" +
    "var myDataModule = angular.module('myApp.myData', []);" +
    "myDataModule.service('MyDataRepository', function() {" +
        "var myData = "+myDataStr+";" +
        "return {" +
            "getData: function () {" +
                "return myData;" +
            "}" +
        "}" +
    "});" +
    "})();"

    // Now send it to the client:
    HttpHeaders responseHeaders = new HttpHeaders();
    responseHeaders.add("Content-Type", "text/javascript");
    return new ResponseEntity<String>(myJS , responseHeaders, HttpStatus.OK);
}

그런 다음 필요할 때마다 MyDataRepository를 주입 할 수 있습니다.

someOtherModule.service('MyOtherService', function(MyDataRepository) {
    var myData = MyDataRepository.getData();
    // Do what you have to do...
}

이것은 나에게 큰 효과가 있었지만, 누군가가 있다면 어떤 피드백에도 열려 있습니다. }


나는 당신의 모듈 방식을 좋아합니다. 데이터를 요청하는 서비스에서 $ routeScope를 사용할 수 있으며 $ http.success 콜백에서 데이터를 할당 할 수 있습니다. 그러나 비전 역 항목에 $ routeScope를 사용하면 냄새가 나고 실제로 $ scope 컨트롤러에 데이터를 할당해야합니다. 불행히도, 혁신적인 반면에, 당신의 접근 방식은 이상적이지 않다고 생각합니다 (그러나 당신에게 맞는 것을 찾는 것에 대한 존중). 어떻게 든 데이터를 기다리고 범위에 할당 할 수있는 클라이언트 측 응답 만 있어야합니다. 검색은 계속됩니다!
dewd

누군가에게 도움이되는 경우 최근에 다른 사람들이 ngModules 웹 사이트에 작성하고 추가 한 모듈을보고있는 다른 접근법을 보았습니다. 더 많은 시간을 가면 그 중 하나를 사용하기 시작하거나 그들이 한 일을 알아 내 물건에 추가해야합니다.
testing123


1

JSONP서비스 데이터를 비동기 적으로로드 하는 데 사용할 수 있습니다 . 초기 페이지로드 중에 JSONP 요청이 작성되고 애플리케이션이 시작되기 전에 결과를 사용할 수 있습니다. 이렇게하면 중복 해결로 라우팅을 확장 할 필요가 없습니다.

html은 다음과 같습니다.

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script>

function MyService {
  this.getData = function(){
    return   MyService.data;
  }
}
MyService.setData = function(data) {
  MyService.data = data;
}

angular.module('main')
.service('MyService', MyService)

</script>
<script src="/some_data.php?jsonp=MyService.setData"></script>

-1

초기화를 가져 오는 가장 쉬운 방법은 ng-init 디렉토리를 사용하십시오.

ng-init div 범위를 init 데이터를 가져 오려는 곳에 두십시오.

index.html

<div class="frame" ng-init="init()">
    <div class="bit-1">
      <div class="field p-r">
        <label ng-show="regi_step2.address" class="show-hide c-t-1 ng-hide" style="">Country</label>
        <select class="form-control w-100" ng-model="country" name="country" id="country" ng-options="item.name for item in countries" ng-change="stateChanged()" >
        </select>
        <textarea class="form-control w-100" ng-model="regi_step2.address" placeholder="Address" name="address" id="address" ng-required="true" style=""></textarea>
      </div>
    </div>
  </div>

index.js

$scope.init=function(){
    $http({method:'GET',url:'/countries/countries.json'}).success(function(data){
      alert();
           $scope.countries = data;
    });
  };

참고 : 한 곳 이상의 코드가없는 경우이 방법을 사용할 수 있습니다.


다음 문서에 따라 ngInit을 사용하지 않는 것이 좋습니다. docs.angularjs.org/api/ng/directive/ngInit
fodma1
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.