NestJS — Node.js للمؤسسات

المزوّدات والخدمات

16 دقيقة الدرس 5 من 48

المزوّدات والخدمات

إن كانت المتحكّمات هي "كيف تَرِد الطلبات"، فالمزوّدات هي "حيث يجري العمل". المزوّد أي صنف يستطيع NestJS حقنه كتبعية — وأشيعها خدمة تحتوي منطق العمل. في هذا الدرس يتّضح أخيرًا مفهوم حقن التبعيات، قلب NestJS.

تعريف خدمة

الخدمة صنف مُعلَّم بالمُزخرِف @Injectable(). يخبر هذا المُزخرِف NestJS: "يمكن إدارة هذا الصنف وحقنه":

import { Injectable } from '@nestjs/common'; @Injectable() export class UsersService { private users = [{ id: 1, name: 'Sara' }]; findAll() { return this.users; } create(name: string) { const user = { id: Date.now(), name }; this.users.push(user); return user; } }

حقن خدمة في متحكّم

أنت لا تستدعي new UsersService() بنفسك. بل تُعلِنها كمعامل في الباني ويزوّدك NestJS بالنسخة — هذا هو حقن التبعيات:

import { Controller, Get, Post, Body } from '@nestjs/common'; import { UsersService } from './users.service'; @Controller('users') export class UsersController { constructor(private readonly usersService: UsersService) {} @Get() findAll() { return this.usersService.findAll(); } @Post() create(@Body('name') name: string) { return this.usersService.create(name); } }

الاختصار private readonly usersService يُعلِن التبعية ويُسنِدها في سطر واحد. يرى NestJS النوع UsersService ويحقن النسخة الصحيحة.

كيف يعرف NestJS ما يحقنه؟ يقرأ أنواع معاملات الباني (بفضل بيانات TypeScript الوصفية) ويبحث عنها في قائمة مزوّدات الوحدة. عند المطابقة → تُحقَن النسخة.

تسجيل المزوّد

كي يعمل الحقن، يجب إدراج الخدمة في مصفوفة providers لوحدةٍ ما:

import { Module } from '@nestjs/common'; import { UsersController } from './users.controller'; import { UsersService } from './users.service'; @Module({ controllers: [UsersController], providers: [UsersService], }) export class UsersModule {}

مفردات (Singletons) افتراضيًا

افتراضيًا كل مزوّد هو مفرد (singleton) — يُنشئ NestJS نسخة واحدة ويشاركها عبر التطبيق كلّه. احقن UsersService في عشرة متحكّمات وستتشارك العشرة الكائن نفسه وحالته.

لماذا يهمّ هذا: يجعل المفرد الخدماتِ مثاليةً للموارد المشتركة كاتصال قاعدة بيانات أو ذاكرة تخزين مؤقت في الذاكرة — تُنشأ مرّة وتُعاد في كل مكان، دون تكرار مُهدِر.

لماذا يتفوّق حقن التبعيات

  • قابلية الاختبار: في الاختبار تحقن خدمة وهميّة بدل الحقيقية — دون تغيير الكود.
  • اقتران مرن: تعتمد الأصناف على تجريدات يوفّرها الحاوي، لا على كائنات تبنيها بنفسها.
  • مسؤولية واحدة: المتحكّمات تُوجّه والخدمات تحسب، ويبقى كلٌّ صغيرًا.
"Nest can't resolve dependencies of the X controller." هذا الخطأ الشائع جدًا عند الإقلاع يعني غالبًا أنّ مزوّدًا مفقود من مصفوفة providers، أو أنّ الوحدة التي تُصدّره لم تُستورَد. اقرأ التلميح بين القوسين في الرسالة — فهو يسمّي التبعية المفقودة.

الخلاصة

المزوّدات — عادةً خدمات مُعلَّمة بـ @Injectable() — تحتوي منطق عملك وتُزوَّد للمتحكّمات عبر حقن الباني. سجّلها في مصفوفة providers للوحدة؛ وهي مفردات افتراضيًا. حقن التبعيات هو ما يُبقي تطبيقات NestJS قابلة للاختبار ومرنة الاقتران وسهلة النمو. بهذا تكتمل المرحلة الأولى: تستطيع الآن بناء واجهة NestJS مُهيكَلة وعاملة.