是否可以在angular bootstrapModule之外实例化一个类并将实例注入应用程序? [英] Is it possible to instantiate a class outside angular bootstrapModule and inject instance into the application?

查看:109
本文介绍了是否可以在angular bootstrapModule之外实例化一个类并将实例注入应用程序?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在main.ts文件中使用服务 authService ,该文件包含 platformBrowserDynamic.bootstrapModule(AppModule);

I am trying to use a service authService in my main.ts file that contains the platformBrowserDynamic.bootstrapModule(AppModule);

该服务处理用户身份验证和令牌续订,我们希望它在应用程序引导之前获取用户令牌。这将避免引导应用程序,重定向到身份验证网页,然后再次引导应用程序。

The service handles the users auth and token renewal, and we would like it to get the user token before the application is bootstrapped. This will avoid bootstrapping the app, redirecting to authentication webpage, then bootstrapping the app again.

下面是我们如何处理JIT编译器的问题,并且它工作正常。但是,如果您想利用AOT(我们这样做),这不起作用。

Below is how we handled the problem for JIT compiler, and It worked. However, this does not work if you want to take advantage of AOT (we do).

// main.ts

... imports ...

let windw: Window = window;
let authService = windw['authService'] = windw['authService'] || new AuthService();

  authService.userLoadededEvent
    .subscribe(user => {
      if (location.pathname.match(/silentrenew/)) {
        authService.completeSilentRenew();
      } else if (user && !user.expired) {
        platformBrowserDynamic().bootstrapModule(AppModule(authService));
      } else {
        if (location.hash.match(/id_token/)) {
          authService.completeSignIn()
        } else {
          if (location.pathname.length > 1) {
            let deeplink = location.href.replace(baseHref, '');
            localStorage.setItem('deeplink', deeplink);
          }
          authService.signIn();
        }
      }
    });







// AppModule

export const AppModule = (authService: AuthService = null) => {
  @NgModule({
    declarations: [
      AppComponent
    ],
    imports: [...],
    providers: [
      {
        provide: AuthService,
        useValue: authService
      }
    ],
    bootstrap: [AppComponent]
  })
  class AppModule { };
  return AppModule;
}

如前所述,这种方法适用于JIT编译,但我希望申请到AOT编译。当我使用上面的代码进行AOT编译时,我从angular得到以下错误。 未处理的承诺拒绝:未找到AppModule的NgModule元数据。 ;区域:< root> ;任务:Promise.then;值:错误:找不到'AppModule'的NgModule元数据。

As stated earlier, this approach works for JIT compilation, but I would like the application to AOT compile. When I AOT compile with the above code, I get the following error from angular. Unhandled Promise rejection: No NgModule metadata found for 'AppModule'. ; Zone: <root> ; Task: Promise.then ; Value: Error: No NgModule metadata found for 'AppModule'.

任何人都知道如何解决此问题? AuthService需要是一个单独的,需要在自举应用程序内外访问。

我尝试过的东西。

我尝试将AppModule更新为不是函数,而只是一个类声明,其中包含一个使用AuthService的提供程序窗口物体但是,angular似乎无法访问附加authService的窗口obj。这导致AuthService 未定义例如

I tried updating AppModule to not be a function, but just a class declaration with a provider that uses the AuthService from the window obj. However, angular doesn't seem to be able to access the window obj where the authService is attached. Which causes the AuthService to be undefined e.g.

//AppModule
let windw: Window = window;

@NgModule({
    declarations: [
      AppComponent
    ],
    imports: [...],
    providers: [
      {
        provide: AuthService,
        useValue: windw['authService'] // undefined
      }
    ],
    bootstrap: [AppComponent]
  })
  class AppModule { };

我也试过将AuthService传递给 bootstrapModule()方法。这不会导致任何引导错误,但是我得到一个Injector错误,提供 AuthService 。我承认,我不完全确定bootstrapModule的CompilerOptions输入上的providers属性有什么角度。
app.component.html:18错误错误:
StaticInjectorError [AuthService]:
NullInjectorError:没有AuthService的提供者!

I also tried passing the the AuthService into the bootstrapModule() method. This doesn't cause any bootstrap error, but then I get an Injector error that AuthService is not provided. I admit, I am not completely sure what angular does with the providers property on the CompilerOptions input for bootstrapModule. app.component.html:18 ERROR Error: StaticInjectorError[AuthService]: NullInjectorError: No provider for AuthService!

// main.ts

... imports ...

let windw: Window = window;
let authService = windw['authService'] = windw['authService'] || new AuthService();

  authService.userLoadededEvent
    .subscribe(user => {
      if (location.pathname.match(/silentrenew/)) {
        authService.completeSilentRenew();
      } else if (user && !user.expired) {
        platformBrowserDynamic().bootstrapModule(AppModule, {
         providers: [{provide: AuthService, useValue: authService}]
        });
      } else {
        if (location.hash.match(/id_token/)) {
          authService.completeSignIn()
        } else {
          if (location.pathname.length > 1) {
            let deeplink = location.href.replace(baseHref, '');
            localStorage.setItem('deeplink', deeplink);
          }
          authService.signIn();
        }
      }
    });







// AppModule

export const AppModule = (authService: AuthService = null) => {
  @NgModule({
    declarations: [
      AppComponent
    ],
    imports: [...],
    providers: [],
    bootstrap: [AppComponent]
  })
  class AppModule { };
  return AppModule;
}

再次感谢您的帮助。

推荐答案

应该在Angular应用程序之外访问类实例的事实并不意味着它应该暴露给全局范围。 ES模块可以自然地提供单例,因为它们被评估一次:

The fact that class instance should be accessed outside Angular application doesn't mean that it should be exposed to global scope. ES modules can naturally provide singletons because they are evaluated once:

export class AuthService { ... }

export default new AuthService(); // default singleton

默认模块导出将只要非Angular应用程序与Angular应用程序一起构建就是单例。

default module export will be a singleton, as long as non-Angular application is being built together with Angular application.

否则 window 应该是在工厂内部使用:

Otherwise window should be used inside factory function:

export function authServiceFactory() {
  return window['authService'] || (window['authService'] = new AuthService);
}
...
providers: [
  {
    provide: AuthService,
    useFactory: authServiceFactory
  }
],
...

这是AOT施加的限制,因为<$ c $在节点环境中编译应用程序时,c> window 不存在。

This is the limitation that is imposed by AOT because window doesn't exist at the time when the application is being compiled in Node environment.

这篇关于是否可以在angular bootstrapModule之外实例化一个类并将实例注入应用程序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆