AngularJS : Initialize service with asynchronous data

后端 未结 10 1910
爱一瞬间的悲伤
爱一瞬间的悲伤 2020-11-22 03:09

I have an AngularJS service that I want to initialize with some asynchronous data. Something like this:

myModule.service(\'MyService\', function($http) {
            


        
10条回答
  •  自闭症患者
    2020-11-22 03:20

    I used a similar approach to the one described by @XMLilley but wanted to have the ability to use AngularJS services like $http to load the configuration and do further initialization without the use of low level APIs or jQuery.

    Using resolve on routes was also not an option because I needed the values to be available as constants when my app is started, even in module.config() blocks.

    I created a small AngularJS app that loads the config, sets them as constants on the actual app and bootstraps it.

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

    See it in action (using $timeout instead of $http) here: http://plnkr.co/edit/FYznxP3xe8dxzwxs37hi?p=preview

    UPDATE

    I would recommend to use the approach described below by Martin Atkins and JBCP.

    UPDATE 2

    Because I needed it in multiple projects, I just released a bower module that takes care of this: https://github.com/philippd/angular-deferred-bootstrap

    Example that loads data from the back-end and sets a constant called APP_CONFIG on the AngularJS module:

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

提交回复
热议问题