Сервис создан дважды после APP_INITIALIZER - PullRequest
0 голосов
/ 09 ноября 2018

Проблема: мне нужно сделать 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 служба приложения снова инициализируется. Я уверен в этом, потому что, если я регистрирую или помещаю оператор отладчика, метод службы () вызывается дважды.

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

Ответы [ 3 ]

0 голосов
/ 14 ноября 2018

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

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

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

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

0 голосов
/ 14 ноября 2018

Причина этого в том, что если вы включите 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

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

export class TestService {

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

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

Разветвленный стек-блиц

0 голосов
/ 12 ноября 2018

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

Из этого блога говорится, что

"Теперь существует новый, рекомендуемый способ регистрации поставщика, напрямую внутри декоратора @Injectable (), используя приписывать. Он принимает «корень» в качестве значения или любой модуль вашего приложение. Когда вы используете «root», ваш инъекционный будет зарегистрирован в приложении, и вам не нужно добавлять его в провайдеры корневого модуля. Точно так же, если вы используете предусмотрено в: UsersModule, инъецируемый зарегистрирован как поставщик UsersModule без добавления его к поставщикам модуля. "

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

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

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

Источник

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

...