نوفيل
الرئيسيةالكورساتالتحديات⚔️ المبارزاتالمقالاتالأدواتتغريداتالمجتمع
دخولابدأ مجاناً
الرئيسيةالكورساتالتحديات⚔️ المبارزاتالمقالاتالأدواتتغريداتالمجتمع
نوفيل

منصة تعليم البرمجة الأولى بالعربي. تعلم من الصفر حتى الاحتراف مع كورسات احترافية وتحديات ذكاء اصطناعي.

المنصة

  • الكورسات
  • التحديات
  • المقالات
  • الأدوات

الحساب

  • إنشاء حساب
  • تسجيل الدخول
  • لوحة التحكم
  • الملف الشخصي

روابط

  • سياسة الخصوصية
  • شروط الاستخدام
  • عن نوفيل
  • تواصل معنا

© 2026 نوفيل. جميع الحقوق محفوظة.

صُنع بـ في مصر

نوفيل
الرئيسيةالكورساتالتحديات⚔️ المبارزاتالمقالاتالأدواتتغريداتالمجتمع
دخولابدأ مجاناً
الرئيسيةالكورساتالتحديات⚔️ المبارزاتالمقالاتالأدواتتغريداتالمجتمع
AN

منهج Angular

دليل مرجعي شامل

كل اللغات
مدرسة البرمجة/منهج Angular /تنقية وتحويل البيانات باستخدام مشغلات الأساسية مثل map و filter و tap

تنقية وتحويل البيانات باستخدام مشغلات الأساسية مثل map و filter و tap

Core RxJS OperatorsData TransformationStream FilteringSide Effectsmapfilter

جدول مرجعي سريع

1
اسم المشغل (`Operator`)دوره المعماري في الـ Pipelineالتأثير المباشر على البيانات المارة
`map`تحويل كل قيمة صادرة من التدفق إلى شكل أو قيمة جديدة بناءً على منطق برمجي محددتغيير محتوى أو هيكل البيانات المارة عبر التدفق
`filter`تمرير القيم التي تطابق شرطاً منطقياً معيناً فقط وحظر البقيةتقليص عدد القيم الصادرة ومنع وصول البيانات غير المرغوبة للمستهلك
`tap`تنفيذ آثار جانبية (`Side Effects`) مثل التسجيل أو المراقبة دون تغيير البياناتتمرير البيانات الأصلية كما هي تماماً للمشغلات التالية دون أي تعديل

الشرح

، لا يتم استخدام التدفقات الخام كما هي غالباً، بل يتم إخضاعها لعمليات معالجة، تنقية، وتحويل داخل خط الأنابيب (pipe). تعتبر المشغلات الأساسية map و filter و tap الأدوات الجوهرية لبناء تدفقات بيانات نظيفة، مفصولة المسؤوليات، وخالية من الآثار الجانبية غير المدروسة.

تفصيل فلسفة وعمل المشغلات الأساسية

التحويل الدلالي عبر map:

يستخدم لتحويل البيانات الخام (مثل استجابة خادم بصيغة JSON) إلى نماذج بيانات مهيكلة تناسب واجهة المستخدم مباشرة، مما يفصل منطق جلب البيانات عن منطق العرض.

التنقية الشرطية عبر filter:

يضمن عدم مرور أي بيانات لا تستوفي الشروط البرمجية (مثل القيم الفارغة أو غير الصالحة)، مما يحمي المكون من الأخطاء المفاجئة.

المراقبة الآمنة عبر tap:

أداة ممتازة لتتبع وتصحيح الأخطاء (Debugging) أو طباعة القيم في وحدة التحكم (Console) دون العبث بمسار البيانات الأصلي.

أمثلة برمجية موسعة: التطبيق العملي لمشغلات map و filter و tap

المثال الأول: دمج المشغلات الثلاثة لمعالجة تدفق أرقام وتصفيتها وتحويلها (core-operators-pipeline.component.ts)

typescript
1import { Component, OnInit } from '@angular/core';
2import { CommonModule } from '@angular/common';
3import { interval, Subscription } from 'rxjs';
4import { map, filter, tap, take } from 'rxjs/operators';
5
6@Component({
7 selector: 'app-core-operators-pipeline',
8 standalone: true,
9 imports: [CommonModule],
10 template: `
11 <div class="operators-card">
12 <h3>معالجة التدفقات باستخدام map و filter و tap</h3>
13 <p><strong>القيمة الأصلية للعداد:</strong> {{ rawValue }}</p>
14 <p><strong>القيمة النهائية بعد الفلترة والتحويل (الأزواج المربعة):</strong> {{ processedValue }}</p>
15 </div>
16 `,
17 styles: [`
18 .operators-card { background: #090d16; color: #fff; padding: 24px; border-radius: 12px; border: 1px solid #1e293b; margin-bottom: 16px; }
19 p { color: #94a3b8; margin: 8px 0; }
20 strong { color: #38bdf8; }
21 `]
22})
23export class CoreOperatorsPipelineComponent implements OnInit {
24 rawValue: number = 0;
25 processedValue: number = 0;
26 private sub!: Subscription;
27
28 ngOnInit(): void {
29 // إنشاء تدفق زمني مستمر واختباره عبر المشغلات الأساسية
30 this.sub = interval(1000).pipe(
31 take(10), // تحديد أول 10 قيم فقط للاختبار
32 tap(val => {
33 this.rawValue = val;
34 console.log('[tap] القيمة الخام الواردة:', val);
35 }),
36 filter(val => val % 2 === 0), // الاحتفاظ بالأرقام الزوجية فقط وحظر الفردية
37 tap(val => console.log('[tap بعد الـ filter] الأرقام الزوجية المتبقية:', val)),
38 map(val => val * val) // تربيع الرقم الزوجي المتبقي
39 ).subscribe({
40 next: (result) => {
41 this.processedValue = result;
42 console.log('[subscribe النهائي] القيمة المحولة:', result);
43 }
44 });
45 }
46
47 ngOnDestroy(): void {
48 if (this.sub) {
49 this.sub.unsubscribe();
50 }
51 }
52}

⚠️ تحذير

تذكر أن ترتيب وضع المشغلات داخل الـ pipe يصنع الفارق الكلي في الأداء والنتيجة! وضع filter قبل map يقلل من عدد العمليات الحسابية أو التحويلات الثقيلة عبر تمرير العناصر المطابقة فقط، بينما وضع map أولاً قد يجبر النظام على معالجة كافة العناصر بلا استثناء ثم تصفيتها لاحقاً، وهو ما يضر بكفاءة التطبيق.

المثال الثاني: تطبيق المشغلات على بيانات مستخدمين قادمة من تدفق تفاعلي (users-stream-filter.component.ts)

typescript
1import { Component, OnInit } from '@angular/core';
2import { CommonModule } from '@angular/common';
3import { of, Subscription } from 'rxjs';
4import { map, filter, tap } from 'rxjs/operators';
5
6interface User {
7 id: number;
8 name: string;
9 isActive: boolean;
10}
11
12@Component({
13 selector: 'app-users-stream-filter',
14 standalone: true,
15 imports: [CommonModule],
16 template: `
17 <div class="operators-card">
18 <h3>تصفية وتحويل قائمة المستخدمين النشطين</h3>
19 <ul>
20 <li *ngFor="let user of activeUserNames">{{ user }}</li>
21 </ul>
22 </div>
23 `,
24 styles: [`
25 .operators-card { background: #090d16; color: #fff; padding: 24px; border-radius: 12px; border: 1px solid #1e293b; }
26 ul { color: #94a3b8; padding-right: 20px; }
27 li { color: #10b981; margin: 4px 0; font-weight: bold; }
28 `]
29})
30export class UsersStreamFilterComponent implements OnInit {
31 activeUserNames: string[] = [];
32 private userSub!: Subscription;
33
34 ngOnInit(): void {
35 const mockUsersList: User[] = [
36 { id: 1, name: 'أحمد محمد', isActive: true },
37 { id: 2, name: 'سارة خالد', isActive: false },
38 { id: 3, name: 'محمود علي', isActive: true },
39 { id: 4, name: 'فاطمة عمر', isActive: false }
40 ];
41
42 // استخدام from/of لمحاكاة تدفق بيانات المستخدمين
43 this.userSub = of(mockUsersList).pipe(
44 tap(users => console.log('إجمالي المستخدمين الخام:', users.length)),
45 // تحويل مصفوفة المستخدمين لفلترتها
46 map(users => users.filter(user => user.isActive)),
47 tap(activeUsers => console.log('عدد المستخدمين النشطين بعد الفلترة الداخلية:', activeUsers.length)),
48 // تحويل مصفوفة الكائنات إلى مصفوفة نصوص تمثل الأسماء فقط
49 map(activeUsers => activeUsers.map(u => u.name))
50 ).subscribe({
51 next: (names) => {
52 this.activeUserNames = names;
53 console.log('الأسماء النهائية المعروضة:', names);
54 }
55 });
56 }
57
58 ngOnDestroy(): void {
59 if (this.userSub) {
60 this.userSub.unsubscribe();
61 }
62 }
63}

نصائح احترافية

  • —اجعل استخدام مشغل tap مخصصاً فقط للعمليات الخارجية مثل التسجيل (Logging) أو تحديث متغيرات جانبية خفيفة، ولا تضع أبداً منطق تحويل البيانات الأساسي داخله!
  • —تحويل البيانات الحقيقي يجب أن يتم دائماً حصرياً داخل مشغل map لضمان وضوح المعمارية وثباتها.

الدرس السابق

التعامل مع أحداث DOM وتدفقات البيانات المستمرة باستخدام

الدرس التالي

معالجة الأخطاء وإعادة المحاولة في التدفقات باستخدام catchError و retry

نوفيل

منصة تعليم البرمجة الأولى بالعربي. تعلم من الصفر حتى الاحتراف مع كورسات احترافية وتحديات ذكاء اصطناعي.

المنصة

  • الكورسات
  • التحديات
  • المقالات
  • الأدوات

الحساب

  • إنشاء حساب
  • تسجيل الدخول
  • لوحة التحكم
  • الملف الشخصي

روابط

  • سياسة الخصوصية
  • شروط الاستخدام
  • عن نوفيل
  • تواصل معنا

© 2026 نوفيل. جميع الحقوق محفوظة.

صُنع بـ في مصر