【问题标题】:How to bootstrap an Angular 2 application asynchronously如何异步引导 Angular 2 应用程序
【发布时间】:2016-07-10 20:35:59
【问题描述】:

excellent article 介绍了如何异步引导 angular1 应用程序。这使我们能够在引导之前从服务器获取 json。

主要代码在这里:

(function() {
    var myApplication = angular.module("myApplication", []);

    fetchData().then(bootstrapApplication);

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

        return $http.get("/path/to/data.json").then(function(response) {
            myApplication.constant("config", response.data);
        }, function(errorResponse) {
            // Handle error case
        });
    }

    function bootstrapApplication() {
        angular.element(document).ready(function() {
            angular.bootstrap(document, ["myApplication"]);
        });
    }
}());

如何使用 Angular 2 实现相同的目标?

【问题讨论】:

  • 同理。 . .
  • 所以我应该看看如何使用 angular2 注入器手动获取 http 客户端?
  • 类似new Injector([HTTP_PROVIDERS]).get(Http)

标签: angularjs angular


【解决方案1】:

Thierry Templier 方法也适用于 jQuery。 这是我使用 angular 2.3.1(文件 main.ts)的解决方案:

import './polyfills.ts';

import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { enableProdMode } from '@angular/core';
import { environment } from './environments/environment';
import { AppModule } from './app/app.module';
declare var $: any;

if (environment.production) {
  enableProdMode();
}

$.ajax({
    'url': './assets/config.json',
    'type': 'GET',
    'success': function(data) {
      platformBrowserDynamic(
        [
          {
            provide: 'appConfig',
            useValue: data
          }
        ]
      ).bootstrapModule(AppModule);
    }
});

【讨论】:

    【解决方案2】:

    我试图解决一个类似的问题,我不仅需要异步引导应用程序,还需要在我的应用程序中使用异步初始化的服务。 这是解决方案,也许对某人有用:

    let injector = ReflectiveInjector.resolveAndCreate([Service1,
    {
        provide: Service2,
        useFactory: (s1: Service1) => new Service1(s2),
        deps: [Service1]
    }]);
    
    let s1: Service1 = injector.get(Service1);
    let s2: Service2 = injector.get(Service2);
    
    s2.initialize().then(() => {
    bootstrap(Application, [
        ...dependencies,
        {
            provide: Service2,
            useValue: s2     // this ensures that the existing instance is used
        }
        // Service2 - this would create a new instance and the init would be lost
        ]);
    }); 
    

    【讨论】:

      【解决方案3】:

      实际上,您需要在应用程序本身之外显式创建一个注入器,以获取Http 的实例来执行请求。然后在 boostrap 应用程序时可以将加载的配置添加到提供程序中。

      这是一个示例:

      import {bootstrap} from 'angular2/platform/browser';
      import {provide, Injector} from 'angular2/core';
      import {HTTP_PROVIDERS, Http} from 'angular2/http';
      import {AppComponent} from './app.component';
      import 'rxjs/Rx';
      
      var injector = Injector.resolveAndCreate([HTTP_PROVIDERS]);
      var http = injector.get(Http);
      
      http.get('data.json').map(res => res.json())
        .subscribe(data => {
          bootstrap(AppComponent, [
            HTTP_PROVIDERS
            provide('config', { useValue: data })
          ]);
        });
      

      然后就可以通过依赖注入访问配置了:

      import {Component, Inject} from 'angular2/core';
      
      @Component({
        selector: 'app',
        template: `
          <div>
            Test
          </div>
        `
      })
      export class AppComponent {
        constructor(@Inject('config') private config) {
          console.log(config);
        }
      }
      

      看到这个 plunkr:https://plnkr.co/edit/kUG4Ee9dHx6TiJSa2WXK?p=preview

      【讨论】:

      • 首先,非常感谢这个解决方案。其次,在这种情况下,promise 会更好吗,因为您可能只期望一个结果,并且在任何一种情况下(成功或失败)都希望得到响应?即http.get('data.json').toPromise() 或者这真的重要吗?
      • @dspie 不客气!我理解您对承诺的评论,但在 http 的情况下,只有一个事件被触发并在之后完成......所以无需转换为承诺 ;-)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-23
      • 1970-01-01
      • 2016-09-06
      • 1970-01-01
      • 2017-05-27
      • 1970-01-01
      相关资源
      最近更新 更多