我想用我从服务中检索的数据来引导我的应用程序.我正在做一些事情
let dependencies = [ //... a load of dependencies MyService ]; let injector = Injector.resolveAndCreate(dependencies); let service: MyService = injector.get(MyService); service.getData() // returns observable .toPromise() .then((d) => { // use data to append to dependencies bootstrap(App,dependencies) });
这工作正常,但我不喜欢两次使用依赖数组,有没有更简洁的方法这样做?我可以在bootstrap之后向应用程序注入器添加内容吗?另外我注意到bootstrap函数返回一个promise,我可以使用这个promise来阻止应用程序的引导直到我的ajax请求完成之后吗?
当然对于Injector我只能使用MyService所需的那些依赖项,但是这使得它非常脆弱,你可以想象.
解决方法
这里的问题是Angular2在引导主要组件之前不允许您访问应用程序引用及其注入器.请参阅源代码中的这一行:
https://github.com/angular/angular/blob/master/modules/angular2/platform/browser.ts#L110.
一种方法可以是实现自定义引导程序而不是使用默认引导程序.类似的东西将应用程序创建和应用程序组件上的boostrapping分开.这样您就可以在两个任务之间加载一些东西.
这是一个示例实现:
function customBoostrap(appComponentType,customProviders) { reflector.reflectionCapabilities = new ReflectionCapabilities(); let appProviders = isPresent(customProviders) ? [BROWSER_APP_PROVIDERS,customProviders] : BROWSER_APP_PROVIDERS; var app = platform(BROWSER_PROVIDERS).application(appProviders); var service = app.injector.get(CompaniesService); return service.getCompanies().flatMap((companies) => { var companiesProvider = new Provider('companies',{ useValue: data }); return app.bootstrap(appComponentType,[ companiesProvider ]); }).toPromise(); }
并以这种方式使用它:
customBoostrap(AppComponent,[ HTTP_PROVIDERS,CompaniesService ]);
公司将自动在组件内注入,例如:
@Component({ (...) }) export class AppComponent { constructor(@Inject('companies') companies) { console.log(companies); } }
见相应的plunkr:https://plnkr.co/edit/RbBrQ7KOMoFVNU2ZG5jM?p=preview.
在这个时候,它有点hacky但这种方法可以作为功能请求提出……
编辑
看了ApplicationRef
课程的文档后,我看到有一个更简单的解决方案;-)
var app = platform(BROWSER_PROVIDERS) .application([BROWSER_APP_PROVIDERS,appProviders]); service.getCompanies().flatMap((companies) => { var companiesProvider = new Provider('companies',{ useValue: data }); return app.bootstrap(appComponentType,[ companiesProvider ]); }).toPromise();
这是相应的plunkr:https://plnkr.co/edit/ooMNzEw2ptWrumwAX5zP?p=preview.