Реалізація патерну Dependency Injection у @ts-stack/di

Усі статті, обговорення, новини про Front-end — в одному місці. Підписуйтеся на телеграм-канал!

@ts-stack/di витягнутий мною з Angular v4.4.7, і являє собою модуль, що відповідає за Dependency Injection, але його можна використовувати у будь-якому TypeScript-проекті, на фронтенді чи бекенді, бо він вже нічого не робить специфічного «тільки для Angular».

Читав багато разів в інтернеті, що одна із найскладніших частин Angular — це його система Dependency Injection. Думаю, що це не так, і насправді місцями переускладненою є лише офіційна документація для DI.

Я спробував виправити це, причому у даній документації немає прив’язки до Angular. Отже, кому потрібен Dependency Injection у TypeScript-проекті, можете користуватись.

👍ПодобаєтьсяСподобалось2
До обраногоВ обраному0
LinkedIn
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

В кометарях Дмитро підказав що є ще tsyringe від microsoft. На перший погляд дуже схожі IoC, але для мене під питанням залишається реєстрація провайдерів:

The normal way to achieve this is to add DependencyContainer.register() statements somewhere in your program some time before your first decorated class is instantiated.
// ...
You can also mark up any class with the @registry() decorator to have the given providers registered upon importing the marked up class. @registry() takes an array of providers like so:

Ось це, якщо я правильно розумію, — дуже незручне обмеження. Можливо далі я виясню що це не так, але поки що я бачу що забезпечення модульності під питанням.

Якщо реєстрація провайдерів повинна відбуватись до першого класу з декоратором, то як я буду імпортувати модулі, в яких вже є зареєстровані провайдери? Ніхто не в курсі?

The normal way to achieve this is to add DependencyContainer.register() statements somewhere in your program some time before your first decorated class is instantiated.

Перший раз звернув увагу на „somewhere” і „before your first decorated class”, а там же ще є інші слова, які усе змінюють =). Так що відбій, все із модульністю мабуть буде добре.

а чим поганий tsyringe від microsoft? Як на мене це комбайн ще той...

Погано, що я не знав про нього раніше. Дякую за підказку, зараз гляну що він може.

Не знаю чи Angular’овський DI і Microsoft’овський писались по одним і тим же стандартам, але API у них дуже схожі. Є звичайно відмінність, але не дуже велика.

На перший погляд зовсім новим є визначений перелік scopes, а тому мені не дуже зрозумілі ResolutionScoped та ContainerScoped.

Перший, типу видає синглтони для усіх ResolutionScoped класів, але лише коли у нього запитують конкретний токен. Так?

А у другому, поки немає прикладів, і не спробував сам, незрозуміле формулювання:

if a child container is made, that child container will resolve an instance unique to it.
// Token provider
{
  token: InjectionToken<T>;
  useToken: InjectionToken<T>;
}

Ги, я колись пропонував у Angular перейменувати їхній useExisting якраз на useToken. Не схотіли.

Приближался конец 2021 года.
Джаваскрипт мучительно переизобретал спринг.

Ага, причому тайпскриптерам платять навіть трохи більше (медіана — $4693), ніж джавістам (медіана — $4600).

«Також необхідно використовувати декоратор @Injectable() над кожним класом, що має залежності.»
Це не помилка? В Ангуларі, цей декоратор прописується тільки в тих класах, які самі можуть бути залежностями.

Давайте візьмемо конкретний приклад:

class Service1 {}

Цей клас немає ніяких залежностей, хоча сам може бути залежністю (як ви пишете). Для того, щоб DI зробив його інстанс, йому не обов’язково мати @Injectable(), бо у нього немає що зчитувати з конструктора.

З іншого боку, якщо говорити за Angular, починаючи з тієї миті, коли вони перейшли на Ivy Renderer, вони почали видавати спочатку варни, що сервіс, який запитують через DI не має @Injectable(), а вже із версії, здається, 13 вони кидають помилку через це.

Я зараз трохи випав із теми Angular, але на скільки я пам’ятаю, по @Injectable() вони орієнтується в процесі tree shaking, щоб знати чи включати даний клас у webpack бандл, чи ні. Тобто вони вже розширили відповідальність для @Injectable().

@ts-stack/di витягнуто ще з Angular v4.4.7, тоді вони точно не мали Ivy Renderer, і @Injectable() був необхідний лише в тих випадках, коли він має залежності, які треба вирішити.

P.S. Після Angular v4.4.7, модуль DI вже почав обростати фічами, специфічними лише для Angular, тому я і не робив оновлень @ts-stack/di на новішу версію.

Підписатись на коментарі