Служба создается дважды после APP_INITIALIZER

Проблема: мне нужно сделать http-вызов и сохранить объект, необходимый для генерации динамических маршрутов. Итак, я воспользовался APP_INITIALIZER.

// app.module.ts
import { ApplicationService } from './application.service';


providers: [
  ApplicationService,
  { 
  provide: APP_INITIALIZER, useFactory: appServiceFactory, deps: 
  [Injector, ApplicationService], multi: true 
  },
],

function appServiceFactory(injector: Injector, appService: ApplicationService): Function {
  return () => {
    return appService.loadApplication().then((app: Application) => {
      /custom logic
      });
    });
  };
}


// application.service.ts
@Injectable({
  providedIn: 'root'
})

// navigation.component.ts
import { ApplicationService } from './application.service';

export class NavigationComponent implements OnInit {

    constructor(private _applicationService: ApplicationService) {
  }
}    

Но внутри navigation.component сервис-приложение снова инициализируется. Я уверен в этом, потому что, если я регистрирую или помещаю оператор отладчика, метод construct () службы вызывается дважды.

Почему, даже если Сервис объявлен как одноэлементный с providedIn: root, восстанавливается?

Можете ли вы показать, как вы импортируете модуль?

Pankaj Parkar 09.11.2018 14:04

@PankajParkar добавлен

lucgenti 09.11.2018 14:15

Я хочу сказать, как вы импортируете модуль в массив imports NgModule. этот модуль загружается лениво или нетерпеливо?

Pankaj Parkar 09.11.2018 14:32

@PankajParkar - сервис загружается внутри корневого модуля. Использую всего 1 модуль.

lucgenti 09.11.2018 14:34

что такое appServiceFactory, я нигде в коде не вижу этой функции.

Pankaj Parkar 09.11.2018 14:39

@PankajParkar добавлен

lucgenti 09.11.2018 14:41

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

Pankaj Parkar 09.11.2018 14:50
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Angular и React для вашего проекта веб-разработки?
Angular и React для вашего проекта веб-разработки?
Когда дело доходит до веб-разработки, выбор правильного front-end фреймворка имеет решающее значение. Angular и React - два самых популярных...
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Мы провели Twitter Space, обсудив несколько проблем, связанных с последними дополнениями в Angular. Также прошла Angular Tiny Conf с 25 докладами.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
Мое недавнее углубление в Angular
Мое недавнее углубление в Angular
Недавно я провел некоторое время, изучая фреймворк Angular, и я хотел поделиться своим опытом со всеми вами. Как человек, который любит глубоко...
Освоение Observables и Subjects в Rxjs:
Освоение Observables и Subjects в Rxjs:
Давайте начнем с основ и постепенно перейдем к более продвинутым концепциям в RxJS в Angular
6
7
3 588
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

На основании вашего объяснения, что вы добавили providedIn: root в application.service.ts, это означает, что он будет добавлен в корневой модуль (например, Appmodule.ts), и снова в Appmodule.ts в вашем массиве provider вы добавляете ApplicationService.

Из этого Блог его состояние, что

"There is now a new, recommended, way to register a provider, directly inside the @Injectable() decorator, using the new providedIn attribute. It accepts 'root' as a value or any module of your application. When you use 'root', your injectable will be registered as a singleton in the application, and you don’t need to add it to the providers of the root module. Similarly, if you use providedIn: UsersModule, the injectable is registered as a provider of the UsersModule without adding it to the providers of the module."

это создает сервис, который нужно восстановить

Edit1: Еще нужно проверить, 1. Как вы называете эту службу, я имею в виду в режиме разработки или в режиме Prod, если это режим разработки, тогда служба будет вызываться дважды.

If you're running in development mode, it will run the function at least twice. since in development mode it does a check, changes, then rechecks to verify, where production mode only does the first check, assuming you've done your quality assurance and resolved any values the get changed post checking.

Источник

Попробуйте проверить в Prod Mode и проверить ..

Если я удалю объявление providedIn: root, он все равно будет создаваться дважды. Кроме того, я не могу удалить его из массива поставщиков, потому что он нужен для функции appServiceFactory, предоставленной для APP_INITIALIZER.

lucgenti 12.11.2018 14:23

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

Tummala Krishna Kishore 13.11.2018 06:00
stackblitz.com/edit/angular-xwyugy, но здесь похоже, что создается только один раз
lucgenti 13.11.2018 12:31

вместо этого в моем приложении это продолжается, даже если enableProdMode ();

lucgenti 13.11.2018 12:57

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

lucgenti 13.11.2018 15:06

@lucgenti как дела? вы подтверждаете, что данные загружаются дважды

Tummala Krishna Kishore 13.11.2018 17:04

Нет, потому что loadApplication (), функция, отвечающая за получение и хранение данных, вызывается только из фабрики. И правильно, что делается так: мне нужно сделать только 1 http-вызов при инициализации приложения, а не 2 вызова.

lucgenti 13.11.2018 17:50

@lucgenti, почему ты пользуешься обещанием? какой-либо причине

Tummala Krishna Kishore 13.11.2018 18:01

APP_INITIALIZER ожидает обещания

lucgenti 14.11.2018 09:11

Обнаружил проблему: это было из-за маршрутизатора, необходимого в качестве зависимости для службы, внедренной в ApplicationService.

См. Пример: https://stackblitz.com/edit/angular-xwyugy

Когда маршрутизатор удаляется из ApplicationService, двойное создание экземпляра исчезает.

Не могу понять почему, поэтому буду ждать лучшего ответа для утверждения.

Была аналогичная проблема, за исключением моей, потому что я добавил родительский модуль в свой модуль, чтобы я мог использовать компонент (загруженный в родительский модуль) в своем модуле. В то время это казалось неправильным, но, как ни странно, это был единственный способ добавить этот конкретный компонент (пробовал все вещи exports и entryComponents). Как бы то ни было, в конечном итоге компонент был извлечен в «общий» модуль, в который я включил свой модуль, и проблема была решена, как и ваша.

Guy Park 26.09.2019 06:40
Ответ принят как подходящий

Причина этого в том, что как только вы включаете Router в зависимости от вашей фабрики APP_INITIALIZER, вы получаете циклическую зависимость (https://github.com/angular/angular/blob/4c2ce4e8ba4c5ac5ce8754d67bc6603eaad4564a/packages/router/src/router_module.ts#L61-L64).

ApplicationService
       |
    TestService
       |
     Router
       |
  ApplicationRef
       |
ApplicationInitStatus
       |
 APP_INITIALIZER
       |
ApplicationService

Чтобы решить эту проблему, вы можете лениво получить Router:

export class TestService {

  get router() {
    return this.injector.get(Router)
  }

  constructor(private _http: HttpClient, private injector: Injector ) {
  }
}

Разветвленный Stackblitz

Я также столкнулся с проблемой, что моя служба была создана дважды, и из того, что я видел в журналах, один конструктор был вызван из файла config.service.ts, а второй - из config.service.js (обратите внимание на разницу в расширениях). Оказалось, что я по ошибке импортировал свой сервис вот так:

import { ConfigService } from '../config/config.service.js';

вместо того:

import { ConfigService } from '../config/config.service';

Изменение его на правильный импорт решило проблему.

супер классный ответ :) Так было и со мной. Большое спасибо.

Jaydip Kalkani 11.10.2021 12:27

Другие вопросы по теме