javascript - 如何将从后端呈现的参数传递给angular2 bootstrap方法

标签 javascript angular

有没有办法将后端呈现的参数传递给 angular2 bootstrap 方法?我想使用 BaseRequestOptions 为所有请求设置 http header 具有从后端提供的值。我的 main.ts 文件如下所示:

import { bootstrap } from '@angular/platform-browser-dynamic';
import { AppComponent } from "./app.component.ts";

bootstrap(AppComponent);

我找到了如何将这个参数传递给根组件(https://stackoverflow.com/a/35553650/3455681),但是当我触发 bootstrap 方法时我需要它...有什么想法吗?

编辑:

webpack.config.js 内容:

module.exports = {
  entry: {
    app: "./Scripts/app/main.ts"
  },

  output: {
    filename: "./Scripts/build/[name].js"
  },

  resolve: {
    extensions: ["", ".ts", ".js"]
  },

  module: {
    loaders: [
      {
        test: /\.ts$/,
        loader: 'ts-loader'
      }
    ]
  }
};

最佳答案

更新2

Plunker example

更新 AOT

要与 AoT 合作,工厂关闭需要搬出

function loadContext(context: ContextService) {
  return () => context.load();
}

@NgModule({
  ...
  providers: [ ..., ContextService, { provide: APP_INITIALIZER, useFactory: loadContext, deps: [ContextService], multi: true } ],

另见 https://github.com/angular/angular/issues/11262

更新 RC.6 和 2.0.0 最终示例

function configServiceFactory (config: ConfigService) {
  return () => config.load();
}

@NgModule({
    declarations: [AppComponent],
    imports: [BrowserModule,
        routes,
        FormsModule,
        HttpModule],
    providers: [AuthService,
        Title,
        appRoutingProviders,
        ConfigService,
        { provide: APP_INITIALIZER,
          useFactory: configServiceFactory
          deps: [ConfigService], 
          multi: true }
    ],
    bootstrap: [AppComponent]
})
export class AppModule { }

如果不需要等待初始化完成,也可以使用`class AppModule{}的构造函数:

class AppModule {
  constructor(/*inject required dependencies */) {...} 
}

提示(循环依赖)

例如,注入(inject)路由器会导致循环依赖。 要解决此问题,请注入(inject) Injector 并通过

获取依赖项
this.myDep = injector.get(MyDependency);

而不是像这样直接注入(inject) MyDependency:

@Injectable()
export class ConfigService {
  private router:Router;
  constructor(/*private router:Router*/ injector:Injector) {
    setTimeout(() => this.router = injector.get(Router));
  }
}

更新

这在 RC.5 中应该是一样的,但是将提供程序添加到根模块的 providers: [...] 而不是 bootstrap(...)

(我自己还没有测试过)。

更新

此处解释了一种完全在 Angular 内部执行此操作的有趣方法 https://github.com/angular/angular/issues/9047#issuecomment-224075188

You can use APP_INITIALIZER which will execute a function when the app is initialized and delay what it provides if the function returns a promise. This means the app can be initializing without quite so much latency and you can also use the existing services and framework features.

As an example, suppose you have a multi-tenanted solution where the site info relies on the domain name it's being served from. This can be [name].letterpress.com or a custom domain which is matched on the full hostname. We can hide the fact that this is behind a promise by using APP_INITIALIZER.

In bootstrap:

{provide: APP_INITIALIZER, useFactory: (sites:SitesService) => () => sites.load(), deps:[SitesService, HTTP_PROVIDERS], multi: true}),

sites.service.ts:

@Injectable()
export class SitesService {
  public current:Site;

  constructor(private http:Http, private config:Config) { }

  load():Promise<Site> {
    var url:string;
    var pos = location.hostname.lastIndexOf(this.config.rootDomain);
    var url = (pos === -1)
      ? this.config.apiEndpoint + '/sites?host=' + location.hostname
      : this.config.apiEndpoint + '/sites/' + location.hostname.substr(0, pos);
    var promise = this.http.get(url).map(res => res.json()).toPromise();
    promise.then(site => this.current = site);
    return promise;
  }

NOTE: config is just a custom config class. rootDomain would be '.letterpress.com' for this example and would allow things like aptaincodeman.letterpress.com.

Any components and other services can now have Site injected into them and use the .current property which will be a concrete populated object with no need to wait on any promise within the app.

This approach seemed to cut the startup latency which was otherwise quite noticeable if you were waiting for the large Angular bundle to load and then another http request before the bootstrap even began.

原创

您可以使用 Angulars 依赖注入(inject)来传递它:

var headers = ... // get the headers from the server

bootstrap(AppComponent, [{provide: 'headers', useValue: headers})]);
class SomeComponentOrService {
   constructor(@Inject('headers') private headers) {}
}

或直接提供准备好的BaseRequestOptions

class MyRequestOptions extends BaseRequestOptions {
  constructor (private headers) {
    super();
  }
} 

var values = ... // get the headers from the server
var headers = new MyRequestOptions(values);

bootstrap(AppComponent, [{provide: BaseRequestOptions, useValue: headers})]);

关于javascript - 如何将从后端呈现的参数传递给angular2 bootstrap方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37611549/

相关文章:

javascript - Spring Boot不支持“删除”

angular - 无法在其他 NgModule 中加载 NgModule 的共享指令

angular - 错误类型错误 : co. 数字不是函数

javascript - Openlayers 映射特征运动动画动态居中的抖动

javascript jquery 子节点

javascript - 将 Facebook Pixel 添加到 Vue 项目

Angular2动画旋转方向?

angular - 数组对象修改时如何触发变化检测?

javascript - 如何使用 NodeJS 在本地测试 AWS Lambda 处理程序?

javascript - 在 Javascript 中将 yyyy-mm-dd 转换为其他日期格式