Проблема: мне нужно сделать 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, восстанавливается?
@PankajParkar добавлен
Я хочу сказать, как вы импортируете модуль в массив imports NgModule. этот модуль загружается лениво или нетерпеливо?
@PankajParkar - сервис загружается внутри корневого модуля. Использую всего 1 модуль.
что такое appServiceFactory, я нигде в коде не вижу этой функции.
@PankajParkar добавлен
Позвольте нам продолжить обсуждение в чате.





На основании вашего объяснения, что вы добавили 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 было бы лучше, если бы вы могли сохранить код в slackblitz или любым другим способом, чтобы он больше помогал при отладке. прямо сейчас мы будем давать решения в каждом конкретном случае, что бесполезно
вместо этого в моем приложении это продолжается, даже если enableProdMode ();
похоже, проблема не в том, что служба создается дважды из-за внедрения зависимостей в компонент. Во время начальной загрузки он был вызван дважды (1 для модуля, 1 для фабрики). Таким образом, данные, полученные с завода, теряются.
@lucgenti как дела? вы подтверждаете, что данные загружаются дважды
Нет, потому что loadApplication (), функция, отвечающая за получение и хранение данных, вызывается только из фабрики. И правильно, что делается так: мне нужно сделать только 1 http-вызов при инициализации приложения, а не 2 вызова.
@lucgenti, почему ты пользуешься обещанием? какой-либо причине
APP_INITIALIZER ожидает обещания
Обнаружил проблему: это было из-за маршрутизатора, необходимого в качестве зависимости для службы, внедренной в ApplicationService.
См. Пример: https://stackblitz.com/edit/angular-xwyugy
Когда маршрутизатор удаляется из ApplicationService, двойное создание экземпляра исчезает.
Не могу понять почему, поэтому буду ждать лучшего ответа для утверждения.
Была аналогичная проблема, за исключением моей, потому что я добавил родительский модуль в свой модуль, чтобы я мог использовать компонент (загруженный в родительский модуль) в своем модуле. В то время это казалось неправильным, но, как ни странно, это был единственный способ добавить этот конкретный компонент (пробовал все вещи exports и entryComponents). Как бы то ни было, в конечном итоге компонент был извлечен в «общий» модуль, в который я включил свой модуль, и проблема была решена, как и ваша.
Причина этого в том, что как только вы включаете 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 ) {
}
}
Я также столкнулся с проблемой, что моя служба была создана дважды, и из того, что я видел в журналах, один конструктор был вызван из файла config.service.ts, а второй - из config.service.js (обратите внимание на разницу в расширениях). Оказалось, что я по ошибке импортировал свой сервис вот так:
import { ConfigService } from '../config/config.service.js';
вместо того:
import { ConfigService } from '../config/config.service';
Изменение его на правильный импорт решило проблему.
супер классный ответ :) Так было и со мной. Большое спасибо.
Можете ли вы показать, как вы импортируете модуль?