Как создать экземпляр одноэлементной службы при загрузке модуля в Angular2

#angular

#angular

Вопрос:

У меня есть служба в angular 2, которая в своем текущем виде только прослушивает события от пользовательского диспетчера, воздействует на них и отправляет другие события через диспетчер.

Таким образом, служба нигде не вводится и я этого не хочу (позже она будет введена в компоненты лениво загруженных модулей).

Служба находится в общем модуле, и я экспортирую ее следующим образом:

 export class SharedModule {
  static forRoot(): ModuleWithProviders {
    return {
      ngModule: SharedModule,
      providers: [Dispatcher, AccountService]
    };
  }
}
  

Как мне убедиться, что он создается при загрузке SharedModule?

Комментарии:

1. Почему вы хотите создать экземпляр службы при загрузке модуля? это кажется немного запутанным, поскольку вы должны полагаться на первый вызов, а не на создание экземпляра.

2. Так что же не так с этим способом? это правильный путь.

3. @Supamiu Служба должна быть создана при загрузке приложения, поскольку она прослушивает события, касающиеся состояния входа в систему, обрабатываемого другой службой. Все потребители сервиса ленивы, поэтому ожидание, пока кто-нибудь из них введет его, наверняка приведет к пропуску важных событий. Кроме того, эти отложенные модули не будут загружены до тех пор, пока AccountService не одобрит. Конечно, есть всевозможные способы обойти это, но я ищу правильный путь.

Ответ №1:

Вы можете использовать конструктор NgModule. В этом примере я использую его для создания экземпляра UserService и replaceReducers() для ngrx/store того, когда я лениво загружаю этот модуль:

 @NgModule({
  declarations: [],
  imports: [
    CommonModule,
    ...
  ],
  providers: [
    UserService,
    ...
  ],

})
export class LazyModule {
  constructor(
    private userService: UserService,
    private store: Store<any>) {
    console.info(`replaceReducer(${ModuleRootReducer.name})`);
    this.store.replaceReducer(ModuleRootReducer);
  }
}
  

Комментарии:

1. Хм .. должен ли я ввести его в конструктор общего модуля или в модуль приложения? Должен ли я хранить его в массиве поставщиков, возвращаемом forRoot в общем модуле, чтобы убедиться, что это общесистемный синглтон?

2. Это не мой AppModule, это модуль, который я загружаю loadChildren: 'app/feature/feature.module#LazyModule' . Я ввел UserService массив providers этого модуля, поэтому он будет доступен для LazyModule и всех других модулей, которые я импортирую сюда. У AppModule нет доступа к UserService , как и не должно быть в моем случае…

3. Потрясающе, это было исправление в одну строку. Я просто ввел его в конструктор общего модуля. Как бы это работало, если бы инициализация AccountService была асинхронной. То есть, если бы я хотел вызвать init(): Promise метод, прежде чем что-либо еще продолжится?

4. Я думаю, вы могли бы вернуть наблюдаемое / обещание, на которое могут подписаться другие службы. Я использую firebase.auth в своем AppModule для аутентификации пользователя, затем при успешном запуске загружаю этот модуль, который загружает пользовательские данные. Затем мои страницы получают доступ к этим пользовательским данным get user(): User { return this.userService.user }; . Я также использовал <div *ngIf="user"> на корневой странице этого маршрута (где <router-outlet> есть)…