Перейти до основного вмісту

Колізії провайдерів

Уявіть, що у вас є Module3, куди ви імпортували Module2 та Module1. Ви зробили такий імпорт, бо вам потрібні відповідно Service2 та Service1 із цих модулів. Ви проглядаєте результат роботи даних сервісів, але по якійсь причині Service1 працює не так як очікується. Ви починаєте дебажити і виявляється, що Service1 експортують обидва модулі: Module2 та Module1. Ви очікували, що Service1 експортуватиметься лише з Module1, але насправді спрацювала та версія, що експортується з Module2.

Щоб цього не сталось, якщо ви імпортуєте два або більше модулі, в яких експортуються неідентичні провайдери з однаковим токеном, Ditsmod кидатиме приблизно таку помилку:

Error: Importing providers to Module3 failed: exports from Module2 and Module1 causes collision with Service1. If Module3 declared in your application (it is not imported from node_modules), you should add Service1 to resolvedCollisionsPer* in this module. For example: resolvedCollisionsPerReq: [ [Service1, Module1] ].

Конкретно у цій ситуації:

  1. і Module1 підмінює, а потім експортує провайдер з токеном Service1;
  2. і Module2 підмінює, а потім експортує провайдер з токеном Service1;
  3. провайдери з токеном Service1 є неідентичними у Module1 та Module2, тобто з Module2 може еспортуватись, наприклад, об'єкт { token: Service1, useValue: {} }, а з Module1 може еспортуватись Service1 у вигляді класу.

І оскільки обидва ці модулі імпортуються у Module3, якраз тому і виникає "колізія провайдерів", розробник може не знати яка із цих підмін буде працювати в Module3.

Вирішення колізії

Якщо Module3 оголошено у вашому застосунку (тобто не імпортовано з node_modules), колізія вирішується шляхом додавання до resolvedCollisionsPer* масиву з двох елементів, де на першому місці йде токен провайдера, а на другому - модуль, з якого потрібно брати відповідний провайдер:

import { Module1, Service1 } from './module1.js';
import { Module2 } from './module2.js';

@featureModule({
imports: [Module2, Module1],
resolvedCollisionsPerReq: [ [Service1, Module1] ]
})
export class Module3 {}

Якщо Module3 ви встановили за допомогою менеджера пакетів (npm, npm run і т.д.), немає сенсу локально змінювати цей модуль щоб вирішити колізію. Така ситуація може виникнути лише якщо Module1 та Module2 експортуються з кореневого модуля, тому вам потрібно видалити один із цих модулів звідти. Ну і, звичайно ж, після цього вам прийдеться явно імпортувати видалений модуль у ті модулі, де він необхідний.