Почему наблюдаемый метод вызывается каждый раз, когда размещается компонент?

#angular

#angular

Вопрос:

У меня есть пользовательский компонент, который зависит от двух сервисов:

 @Component({
    selector: 'app-search-reon',
    templateUrl: './search-reon.component.html',
    styleUrls: ['./search-reon.component.scss'],
    providers: [
        ReonSearchState,
        {
            provide: SEARCH_PARAMETERS_CADNUM,
            useValue: { layers: [335], types: [201, 207], helpSearch: false, searchText: '', searchType: 2 },
        },
        {
            provide: SEARCH_PARAMETERS_ADDRESS,
            useValue: { layers: [335], types: [203], helpSearch: false, searchText: '', searchType: 2 },
        },
        {
            provide: SEARCH_PARAMETERS_UNOM,
            useValue: { layers: [335], types: [202], helpSearch: false, searchText: '', searchType: 2 },
        },
        { provide: SEARCH_CONFIG_CADNUM, useClass: SearchConfig, deps: [SEARCH_PARAMETERS_CADNUM] },
        { provide: SEARCH_CONFIG_ADDRESS, useClass: SearchConfig, deps: [SEARCH_PARAMETERS_ADDRESS] },
        { provide: SEARCH_CONFIG_UNUM, useClass: SearchConfig, deps: [SEARCH_PARAMETERS_UNOM] },
        {
            provide: ReonSearch,
            useFactory: reonServiceFactory,
            deps: [ReonCloudEsService, ReonSearchState],
        },
    ],
})
export class SearchReonComponent implements OnInit {
    @Input() searchType: ReonSearchType;
    @Output() onSelected = new EventEmitter<any>();

    public selectedObjectValue: any;
    private reonSearch: ReonSearch;

    constructor(
        @Inject(ReonSearch) public reonServiceFactory: any,
        @Inject(SEARCH_CONFIG_CADNUM) public searchCadnumConfig: SearchConfig,
        @Inject(SEARCH_CONFIG_ADDRESS) public searchAddressConfig: SearchConfig,
        @Inject(SEARCH_CONFIG_UNUM) public searchUnumConfig: SearchConfig,
    ) {}

    ngOnInit() {
        try {
            this.factoryReonSearch(this.searchType);
        } catch (e) {
            console.log('ERROR:'   e);
        }

        this.selectedObject.subscribe((value) => {
            this.selectedObjectValue = value;
        });
    }

    private factoryReonSearch(searchType: ReonSearchType): void {
        switch (searchType) {
            case ReonSearchType.CADNUM:
                this.reonSearch = this.reonServiceFactory(this.searchCadnumConfig, searchType);
                break;
            case ReonSearchType.ADDRESS:
                this.reonSearch = this.reonServiceFactory(this.searchAddressConfig, searchType);
                break;
            case ReonSearchType.UNOM:
                this.reonSearch = this.reonServiceFactory(this.searchUnumConfig, searchType);
                break;
            default:
                throw Error('No provider for search type!');
        }
    }

    public get isLoading(): Observable<boolean> {
        return this.reonSearch.isLoading;
    }

    public get objects(): Observable<any> {
        return this.reonSearch.objects;
    }

    public get selectedObject(): Observable<any> {
        return this.reonSearch.selectedObject;
    }

    public selectionChange($event: MatSelectChange): void {
        this.reonSearch.setSelectedObject($event.value);
        this.onSelected.emit($event.value);
    }

    public search($event): void {
        this.reonSearch.search($event);
    }
}
  

Только один триггер события (запрос на сервер):

    public search($event): void {
        this.reonSearch.search($event);
    }
  

У этого компонента есть собственный модуль:

 const modules = [CommonModule, MaterialModule, FormsModule, ReactiveFormsModule, NgxMatSelectSearchModule];
const components = [SearchReonComponent];

@NgModule({
    declarations: [...components],
    imports: [...modules],
    exports: [...components],
    providers: [ReonCloudEsService],
})
export class SearchReonModule {}
  

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

 <app-search-reon [searchType]="ReonSearchType.CADNUM"></app-search-reon>
  

Как вы можете видеть, этот компонент использует factory для предоставления ReonSearch объекта в компоненте.

Это выглядит так:

 export class ReonSearch {
    public searchEvent = new BehaviorSubject<string>(null);
    public loading = new BehaviorSubject<boolean>(false);

    private cadnums: any[] = [];
    private addresses: any[] = [];
    private unoms: any[] = [];
    private response: any[] = [];

    constructor(
        private reonCloudService: ReonCloudEsService,
        private searchConfig: SearchConfig,
        private searchType: ReonSearchType,
        private reonSearchState: ReonSearchState,
    ) {
        this.searchEvent.pipe(switchMap(() => this.reonCloudService.search(this.searchConfig.parameters))).subscribe(); // REUEST TO SERVER
}
  

Почему каждый раз, когда я открываю любое диалоговое окно, в котором импортируется SearchReonModule , я вижу запрос к серверу в ReonSearch строке:

 this.reonCloudService.search(this.searchConfig.parameters)
  

Для кого это событие this.searchEvent ? Почему Angular не создает отдельные экземпляры ReonSearch ReonSearchState для каждого используемого компонента?

ВАЖНО:

Я заметил, что конструктор ReonSearch вызывается столько раз, сколько было использовано component в разных модулях (диалоговых компонентах).

ОСНОВНОЙ ВОПРОС:

Почему, несмотря на то, что у компонента есть поставщик, Angular не создает отдельные instnaces для: ReonSearch , ReonSearchState внутри компонента:

   {
            provide: ReonSearch,
            useFactory: reonServiceFactory,
            deps: [ReonCloudEsService, ReonSearchState],
        },
  

И почему один компонент влияет на другие?

Кажется, я ошибаюсь, я проверил все компоненты, завод каждый раз снова работает:

 export const reonServiceFactory = (reonCloudEsService: ReonCloudEsService, reonSearchState: ReonSearchState) => {
    console.log('works');
}
  

Итак, если в tmeplate есть два компонента, я вижу три раза works . Но что не так с this.searchEvent ? Как это влияет на другие компоненты?

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

1. Я попытаюсь воспроизвести это в StackBlitz

2. Может быть, как-то отказаться от подписки this.searchEvent в конструкторе?

3. Кто может объяснить мне, как создать изолированные компоненты в случае повторного использования в разных компонентах в шаблоне?