如何从后端传递参数到 angular2自助法

有没有办法把后端呈现的参数传递给 angular2自助法?我希望使用 BaseRequestOptions为所有请求设置 http 头,并从后端提供值。我的 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'
}
]
}
};
59689 次浏览

更新2

笨蛋的例子

更新 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

Update an 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 { }

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

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

提示(循环依赖)

例如,注入路由器会导致循环依赖。 要解决这个问题,请注入 Injector并通过以下方法获得依赖项

this.myDep = injector.get(MyDependency);

而不是像这样直接注射 MyDependency:

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

更新

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

(还没有测试自己)。

更新

一个有趣的方法来做它完全内角是在这里解释 https://github.com/angular/angular/issues/9047#issuecomment-224075188

时执行一个函数 应用程序被初始化,如果函数返回,则延迟它所提供的内容 这意味着应用程序可以初始化没有完全如此 大量的延迟,你也可以使用现有的服务和框架 特征。

例如,假设您有一个多租户解决方案,其中 网站信息依赖于提供服务的域名 [ name ] . letterpress.com 或者在 完整的主机名。我们可以隐藏的事实,这是背后的承诺 使用 APP_INITIALIZER

在引导程序中:

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

网址服务网址:

@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;
}

注意: config只是一个自定义配置类 对于这个例子,'.letterpress.com'允许 aptaincodeman.letterpress.com.

任何组件和其他服务现在都可以注入 Site 它们,并使用 .current属性,这将是一个具体的 填充对象,不需要等待应用程序中的任何承诺。

这种方法似乎减少了启动延迟 如果你在等待大的角束 加载,然后在引导程序开始之前再加载另一个 http 请求。

原创的

你可以用角度依赖注入:

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

唯一的方法是在定义提供程序时提供这些值:

bootstrap(AppComponent, [
provide(RequestOptions, { useFactory: () => {
return new CustomRequestOptions(/* parameters here */);
});
]);

然后您可以在 CustomRequestOptions类中使用这些参数:

export class AppRequestOptions extends BaseRequestOptions {
constructor(parameters) {
this.parameters = parameters;
}
}

如果你从一个 AJAX 请求中得到这些参数,你需要以这种方式异步引导:

var appProviders = [ HTTP_PROVIDERS ]


var app = platform(BROWSER_PROVIDERS)
.application([BROWSER_APP_PROVIDERS, appProviders]);


var http = app.injector.get(Http);
http.get('http://.../some path').flatMap((parameters) => {
return app.bootstrap(appComponentType, [
provide(RequestOptions, { useFactory: () => {
return new CustomRequestOptions(/* parameters here */);
}})
]);
}).toPromise();

看这个问题:

剪辑

由于您的数据在 HTML 中,因此可以使用以下内容。

您可以导入一个函数并使用参数调用它。

下面是引导应用程序的主模块示例:

import {bootstrap} from '...';
import {provide} from '...';
import {AppComponent} from '...';


export function main(params) {
bootstrap(AppComponent, [
provide(RequestOptions, { useFactory: () => {
return new CustomRequestOptions(params);
});
]);
}

然后你可以像下面这样从你的 HTML 主页导入:

<script>
var params = {"token": "@User.Token", "xxx": "@User.Yyy"};
System.import('app/main').then((module) => {
module.main(params);
});
</script>

看这个问题: 将常量值传递给 Angular from _ layout.cshtml

在 Angular2最终版本中,可以使用 APP _ INITIALIZER 提供程序来实现所需的功能。

我用一个完整的例子写了一个 Gist: https://gist.github.com/fernandohu/122e88c3bcd210bbe41c608c36306db9

Gist 示例从 JSON 文件读取,但是可以很容易地更改为从 REST 端点读取。

你所需要的,基本上是:

A)在已存在的模块文件中设置 APP _ INITIALIZER:

import { APP_INITIALIZER } from '@angular/core';
import { BackendRequestClass } from './backend.request';
import { HttpModule } from '@angular/http';


...


@NgModule({
imports: [
...
HttpModule
],
...
providers: [
...
...
BackendRequestClass,
{ provide: APP_INITIALIZER, useFactory: (config: BackendRequestClass) => () => config.load(), deps: [BackendRequestClass], multi: true }
],
...
});

这些行将在应用程序启动之前从 BackendRequestClass 类调用 load ()方法。

如果要使用库中内置的 angular2对后端进行 http 调用,请确保在“导入”部分设置“ HttpModule”。

B)创建一个类并将文件命名为“ backend.request.ts”:

import { Inject, Injectable } from '@angular/core';
import { Http } from '@angular/http';
import { Observable } from 'rxjs/Rx';


@Injectable()
export class BackendRequestClass {


private result: Object = null;


constructor(private http: Http) {


}


public getResult() {
return this.result;
}


public load() {
return new Promise((resolve, reject) => {
this.http.get('http://address/of/your/backend/endpoint').map( res => res.json() ).catch((error: any):any => {
reject(false);
return Observable.throw(error.json().error || 'Server error');
}).subscribe( (callResult) => {
this.result = callResult;
resolve(true);
});


});
}
}

C)要读取后端调用的内容,只需将 BackendRequestClass 注入到您选择的任何类中,然后调用 getResult ()。例如:

import { BackendRequestClass } from './backend.request';


export class AnyClass {
constructor(private backendRequest: BackendRequestClass) {
// note that BackendRequestClass is injected into a private property of AnyClass
}


anyMethod() {
this.backendRequest.getResult(); // This should return the data you want
}
}

如果这能解决你的问题就告诉我。

与其让入口点调用 bootstrap 本身,不如创建并导出一个函数来完成这项工作:

export function doBootstrap(data: any) {
platformBrowserDynamic([{provide: Params, useValue: new Params(data)}])
.bootstrapModule(AppModule)
.catch(err => console.error(err));
}

您还可以根据您的设置(webpack/SystemJS)将此函数放在全局对象上。

这样做还有一个额外的好处,那就是可以延迟引导程序。例如,当您在用户填写表单后以 AJAX 调用的形式检索此用户数据时。只需用这些数据调用导出的引导函数。