محتويات الدورة

Angular / المتوسط / الدرس 7

حقن الاعتماديات ونطاق الخدمة

اختر موضع توفير الاعتمادية وافهم عمر نسختها ولا تستدع inject إلا في سياق مدعوم.

وقت القراءة التقريبي: 3 دقيقةتاريخ مراجعة المحتوى
في هذه الصفحة

أهداف الدرس

  • تمييز الرمز والمزود والحاقن والنسخة.
  • شرح حالة الخدمة الجذرية والمحلية للمكوّن.
  • اختبار استبدال الاعتمادية دون إعداد عام متغير.

يحدد الرمز اعتمادية لا متغيرًا عامًا

يفصل الحقن العملية عن كائناتها، ويخبر المزود الحاقن بتوفير قيمة أو صنف أو مصنع أو رمز آخر. تفيد InjectionToken للإعداد والعقود الشبيهة بالواجهة لأن واجهة TypeScript لا توجد فعليًا. يملك الحاقن الحل وفق النطاق والتدرج. لا تجعل أوصاف رمزين متشابهة هويتهما واحدة؛ عرّف الرمز مرة واستورد كائنه نفسه عند التوفير والطلب.

فحص التدرج بحاقن محلي مكتمل

يوفر البرنامج رمزًا بالجذر ويستبدله بالابن، فيقرأ الابن المحلي ويحفظ الجذر قيمته. يختبر حل Angular دون مكوّن أو متصفح، وتنهي destroy الأعمار المحلية. يحتاج مزود المكوّن أيضًا اختبار تدرج العرض. لا تعتبر providedIn: root نسخة واحدة لكل عملية عبر التطبيقات المستقلة أو طلبات الخادم؛ فالنطاق تابع للحاقن المالك.

typescript فحص مكتمل لتدرج مزودين محليين
import { InjectionToken, Injector } from "@angular/core";
const LABEL = new InjectionToken<string>("course label");
const root = Injector.create({ providers: [{ provide: LABEL, useValue: "root" }] });
const child = Injector.create({ parent: root, providers: [{ provide: LABEL, useValue: "feature" }] });
console.log(root.get(LABEL), child.get(LABEL));
child.destroy();
root.destroy();
الناتج المتوقع
root feature

السطر root feature؛ يغير الاستبدال حل الابن دون تعديل مزود الجذر.

تحديد مالك حالة الخدمة المتغيرة

يحوي المثال حالة اختيار ويوفرها المكوّن، فتملك كل نسخة خدمة وتراها الذرية ما لم يستبدلها أقرب. قد يفصل توفيرها ثانية حالةً كان يجب مشاركتها. تشارك الجذرية داخل عمر حاقن التطبيق. اختر النطاق من ملكية الميزة وتنظيفها لا عادة التعميم. يحتاج المثال إنشاء Angular للمضيف؛ فلا يعيد الإنشاء المباشر النطاق.

typescript خدمة حالة سياقية يملكها المكوّن
import { Component, Injectable, inject, signal } from "@angular/core";
@Injectable()
export class SelectionStore { readonly selected = signal<number | null>(null); }
@Component({
  selector: "app-selection-panel", standalone: true, providers: [SelectionStore],
  template: `<p>Selected: {{ store.selected() ?? "none" }}</p>`
})
export class SelectionPanel { readonly store = inject(SelectionStore); }

يمتلك مضيفان مستقلان اختيارين منفصلين؛ وتحتاج ملاحظة الملكية تجربة مكوّن لم تُنفّذ هنا.

السياق شرط تنفيذي لا اسم صنف

تصح inject أثناء تهيئة أو بناء تنفذه DI ومصانعها. لا يصير معالج حدث أو ngOnInit سياقًا تلقائيًا. التقط الاعتمادية عند التهيئة واستعملها لاحقًا. تنشئ runInInjectionContext سياقًا متزامنًا ولا تمده عبر await، وقد تقبل واجهة Injector صريحة. يختلف غياب المزود من غياب السياق فلا تصلحهما بمزودين عامين عشوائيين.

اختبار الهوية والاستبدال والتنظيف

اختبر مشاركة النسخة والاستبدال المقصود وتحرير موارد المالك. استبدل الخارج بمزود اختبار ضيق دون تعديل الإنتاج. يختبر أسلوب خالص المنطق ويختبر DI الإنشاء والنطاق. تجنب منشئًا يطلب شبكة قبل توفير المحاكي. سجّل فشل المزود بسياق رمز مفيد دون أسرار. يجعل التدرج الواضح المشاركة قرارًا لا اكتشافًا عرضيًا.

الأخطاء الشائعة وإصلاحها

ترمي inject خارج سياق مدعوم.

لماذا يحدث؟
استُدعيت من أسلوب عادي لاحق.
كيف تصلحه؟
التقط الاعتمادية عند التهيئة المدعومة.
كيف تتجنب تكراره؟
قرّب نداء السياق من إنشاء مالكه.

يعرض فرعيان حالة مشتركة مختلفة.

لماذا يحدث؟
ينشئ مزود أقرب نسخة أخرى.
كيف تصلحه؟
وفر عند المالك المشترك وأزل الاستبدال العرضي.
كيف تتجنب تكراره؟
اختبر هوية الخدمة عبر التدرج.

رمز لا يُحل رغم تطابق الوصف.

لماذا يحدث؟
أُنشئت كائنات InjectionToken مختلفة.
كيف تصلحه؟
استورد الرمز المصدّر الواحد.
كيف تتجنب تكراره؟
عامل هوية الرمز جزءًا من العقد.

اختبر فهمك

1. احذف استبدال الابن وتوقع السطر وهل نُسخت قيمة الجذر أم حُلّت عبره.

اعرض الحل المشروح

يصير السطر root root لحل الرمز عبر الوالد، لا نسخ إعداد أو إنشاء رمز. أضف اختبار حل وهوية للخدمة المعدلة لحماية المشاركة، وتبقى بنية المكوّن محتاجة تجربتها.

2. يستدعي معالج الزر inject(SelectionStore). صف الإصلاح دون تغيير النطاق.

اعرض الحل المشروح

هيّئ حقلًا بـinject أثناء إنشاء Angular واستعمله بالمعالج مع إبقاء المزود عند مالكه. نقله للجذر لإخفاء الخطأ يغير العمر وقد يولد عيبًا. اختبر الحدث وهوية النسخة.

أهم ما تعلمته

  • يحدد مكان المزود الملكية والنطاق.
  • هوية الرمز والسياق حقائق تنفيذية.
  • اختبر DI مستقلًا عن منطق الخدمة الخالص.

المراجع الرسمية