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

В разделе часто задаваемых вопросов angular docs говорится: «В отличие от поставщиков модулей, загружаемых при запуске, поставщики модулей с отложенной загрузкой имеют область видимости модуля». ссылка

Означает ли здесь «область видимости модуля» только модуль или оно распространяется на все компоненты, принадлежащие этому модулю?

Причина, по которой я спрашиваю, заключается в том, что у меня есть модуль с отложенной загрузкой с двумя принадлежащими ему компонентами. Я регистрирую службу в модуле, но по какой-то причине каждый компонент получает отдельный экземпляр этой службы.

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

Модуль с отложенной загрузкой:

import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { Component1 } from './component1.component';
import { Component2 } from './component2.component';
import { LazyModuleService } from './lazy-module.service';

@NgModule({
  imports: [
    CommonModule,
  ],
  declarations: [
    Component1,
    Component2,
  ],
})

export class LazyLoadedModule { }

person FlashBanistan    schedule 17.03.2017    source источник
comment
у вас есть LazyModuleService, настроенный как поставщик в любом из ваших компонентов вашего ленивого модуля?   -  person snorkpete    schedule 17.03.2017
comment
Нет. Он настраивается только в модуле LazyLoaded.   -  person FlashBanistan    schedule 17.03.2017
comment
Я предполагаю, что это опечатка, но у вас нет LazyModuleService в качестве поставщика в вашем LazyModule   -  person snorkpete    schedule 17.03.2017
comment
Не прямо здесь, но в моем реальном коде я это делаю, и он не работает.   -  person FlashBanistan    schedule 17.03.2017
comment
Можете ли вы попробовать сделать свой модуль НЕ ленивым на время загрузки, просто чтобы посмотреть, сохраняется ли проблема с дублированным сервисом? если модуль не загружается лениво, у вас обязательно должен быть один экземпляр, совместно используемый всеми компонентами (включая те, которые находятся вне модуля). Если этого не происходит, значит, с вашей конфигурацией что-то не так, и это не имеет ничего общего с отложенной загрузкой.   -  person snorkpete    schedule 17.03.2017
comment
Если я предоставляю службу на корневом уровне приложения, тогда все работает нормально, но я не хочу, чтобы служба создавалась до тех пор, пока пользователь не перейдет к этому конкретному модулю.   -  person FlashBanistan    schedule 17.03.2017
comment
Позвольте нам продолжить это обсуждение в чате.   -  person snorkpete    schedule 17.03.2017


Ответы (3)


Как работает ленивая загрузка:

После некоторого глубокого исследования кажется, что проблема связана с тем, как реализована отложенная загрузка.

В вашем случае у вашего ленивого загруженного модуля на самом деле была маршрутизация к двум различным компонентам внутри него - оба эти компонента были напрямую представлены как маршруты Router.forChild. Но в результате, когда вы переходили к каждому компоненту, к каждому компоненту добавлялся отдельный экземпляр поставщиков вашего лениво загруженного модуля.

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

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

Решением было создание единого корневого компонента, инжектор которого будет получать ленивые загружаемые сервисы, которые затем могут использоваться любыми дочерними компонентами.

person snorkpete    schedule 17.03.2017
comment
Мог ли бис применяться к моей проблеме здесь: stackoverflow.com/questions/57688978/ В моем случае я предоставляю услугу в родительском модуле. - person Stefan Falk; 28.08.2019

Отличное встроенное решение, предоставляемое Angular 6. Если вы используете Angular 6+ (проверьте свой package.json, чтобы узнать), вы можете предоставлять услуги для всего приложения другим способом.

Вместо того, чтобы добавлять класс обслуживания в массив Provider [] в AppModule, вы можете установить следующую конфигурацию в @Injectable ():

@Injectable({providedIn: 'root'})
export class MyService { ... }

Это точно так же, как:

export class MyService { ... }

и

import { MyService } from './path/to/my.service';

@NgModule({
    ...
    providers: [MyService]
})
export class MyService { ... }

Использование этого нового синтаксиса совершенно необязательно, традиционный синтаксис (с использованием Provider []) по-прежнему будет работать. Однако «новый синтаксис» имеет одно преимущество: сервисы могут загружаться с помощью Angular лениво (за кулисами), а избыточный код может автоматически удаляться. Это может привести к повышению производительности и скорости загрузки - хотя на самом деле это работает только для более крупных сервисов и приложений в целом.

Источник: Udemy

person Vijay Barot    schedule 06.07.2018
comment
Вы сами это проверили, для меня это не работает. Причина проблемы связана с механизмом отложенной загрузки ... - person DicBrus; 03.12.2018
comment
@DicBrus, это действительно работает, вам придется удалить этот MyService из providers списка этого лениво загруженного модуля. - person Sagar Guhe; 01.02.2019

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

person Тодор Иванов    schedule 17.03.2017
comment
Нет, это не работает. Как я уже сказал в своем вопросе, у меня это так, и это не работает. - person FlashBanistan; 17.03.2017