تعمّق في حقن التبعيات
تعمّق في حقن التبعيات
لقد استخدمت حقن التبعيات سلفًا — بإعلان خدمة في الباني وترك NestJS يزوّدها. والآن لنفتح الصندوق. فهمُ حاوي IoC ورموز المزوّدات (tokens) يحوّل الحقن من سحر إلى أداة تتحكّم بها كاملًا.
حاوي IoC
IoC تعني عكس التحكّم. بدل أن تُنشئ أصنافك تبعياتها بنفسها، يُنشئها ويزوّدها حاوٍ مركزي. عند الإقلاع، يمسح NestJS كل وحدة، ويبني خريطة للمزوّدات، ثم يُنشئها بالترتيب الصحيح، حاقنًا تبعيات كلٍّ منها.
new UsersService(new Database(...)). تُعلِن ما يحتاجه كل صنف، ويُجمِّع الحاوي الرسم البياني كاملًا لك.
رموز المزوّدات
يُسجَّل كل مزوّد تحت رمز (token) — مفتاح يستخدمه الحاوي لإيجاده. مع الاختصار القياسي، الرمز هو الصنف نفسه:
فحين يطلب باني الصنف UsersService، يبحث الحاوي عن الرمز UsersService ويحقن النسخة المطابقة. الصنف يقوم بدورَي النوع ومفتاح البحث معًا.
الحقن برمز غير صنفي
أحيانًا لا يوجد صنف يُستخدم كرمز — ككائن إعدادات أو قيمة بسيطة. تُسجّلها تحت رمز نصّي أو رمزي وتحقنها بـ @Inject():
export const API_KEY = 'API_KEY'). فهي تتفادى الأخطاء المطبعية وتتيح لمحرّرك إيجاد كل استخدام.
التبعيات الاختيارية
إن كانت تبعية قد تكون غائبة، علّمها بـ @Optional() ليحقن الحاوي undefined بدل رمي خطأ:
التبعيات الدائرية
إن اعتمد مزوّدان أحدهما على الآخر، فلا يستطيع الحاوي تحديد أيّهما يُبنى أولًا. يحلّ NestJS ذلك بـ forwardRef() التي تؤجّل المرجع حتى يوجد كلاهما:
forwardRef()، اسأل هل يجب أن يكون المنطق المشترك في خدمة ثالثة يعتمد عليها الاثنان. استخدم forwardRef() كملاذ أخير لا كعادة.
الخلاصة
يبني حاوي IoC في NestJS رسم تبعياتك من رموز المزوّدات. مع اختصار الصنف يكون الصنف هو الرمز؛ وللقيم والواجهات تُسجّل تحت رمز نصّي/رمزي وتحقن بـ @Inject(). تسمح @Optional() بتبعيات غائبة، وتعالج forwardRef() المراجع الدائرية التي لا مفرّ منها. تاليًا نستكشف الطرق الأربع لتعريف مزوّد.