WebSockets
تُعد WebSockets في أنجولار تقنية متقدمة تمكّن من إنشاء اتصالات ثنائية الاتجاه (Full-Duplex) بين العميل (Client) والخادم (Server) في الوقت الحقيقي. بخلاف HTTP التقليدي، الذي يعتمد على الطلب والاستجابة، تسمح WebSockets بتدفق البيانات بشكل مستمر ودون الحاجة إلى إعادة إرسال الطلبات. هذه الميزة تجعلها مثالية لتطبيقات الزمن الحقيقي مثل الدردشة (Chat)، التحديثات الحية (Live Updates)، الألعاب التفاعلية، ولوحات التحكم الديناميكية (Dashboards).
في تطوير أنجولار، يتم دمج WebSockets ضمن هيكلية المكونات (Components) وإدارة الحالة (State Management) لتأمين تفاعل سلس بين الواجهة والمصدر الخلفي للبيانات. يمكن للمطورين استخدام مكتبات مثل RxJS لإدارة تدفق البيانات بطريقة تفاعلية (Reactive Programming) وتحويل الرسائل إلى تدفقات قابلة للمراقبة (Observables).
في هذا الدرس، سيتعلم القارئ كيفية إنشاء خدمة WebSocket في أنجولار، ربطها بالمكونات، إدارة دورة حياة الاتصال، واستخدام أنماط التصميم المتقدمة لتحقيق أداء أمثل. كما سيتم التركيز على كيفية تحسين الأداء وتجنب الأخطاء الشائعة مثل إعادة الرندرة غير الضرورية أو التلاعب المباشر بالحالة.
تتكامل WebSockets في أنجولار بسلاسة مع تطبيقات الويب الحديثة (SPAs)، مما يجعلها أداة قوية لتطوير تطبيقات غنية بالبيانات والوظائف التفاعلية.
مثال أساسي
typescript// إنشاء مثال أساسي على استخدام WebSocket في أنجولار
// 1. إنشاء خدمة WebSocket
import { Injectable, OnDestroy } from '@angular/core';
import { webSocket, WebSocketSubject } from 'rxjs/webSocket';
import { Observable, Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
@Injectable({
providedIn: 'root'
})
export class ChatWebSocketService implements OnDestroy {
private socket$: WebSocketSubject<any>;
private destroy$ = new Subject<void>();
connect(): void {
this.socket$ = webSocket('wss://echo.websocket.org');
this.socket$.pipe(takeUntil(this.destroy$)).subscribe({
next: (message) => console.log('تم استقبال رسالة:', message),
error: (err) => console.error('خطأ في الاتصال:', err),
complete: () => console.log('تم إغلاق الاتصال.')
});
}
sendMessage(msg: string): void {
if (this.socket$) {
this.socket$.next(msg);
}
}
getMessages(): Observable<any> {
return this.socket$.asObservable();
}
ngOnDestroy(): void {
this.destroy$.next();
this.destroy$.complete();
this.socket$?.complete();
}
}
// 2. إنشاء مكون واجهة لعرض الرسائل
import { Component, OnInit, OnDestroy } from '@angular/core';
import { ChatWebSocketService } from './chat-websocket.service';
import { Subscription } from 'rxjs';
@Component({
selector: 'app-chat',
template: ` <div> <h2>تطبيق دردشة عبر WebSocket</h2> <input [(ngModel)]="message" placeholder="اكتب رسالة..." /> <button (click)="send()">إرسال</button> <ul> <li *ngFor="let msg of messages">{{ msg }}</li> </ul> </div>
`
})
export class ChatComponent implements OnInit, OnDestroy {
message = '';
messages: string[] = [];
private sub!: Subscription;
constructor(private chatService: ChatWebSocketService) {}
ngOnInit(): void {
this.chatService.connect();
this.sub = this.chatService.getMessages().subscribe((msg) => {
this.messages.push(msg);
});
}
send(): void {
this.chatService.sendMessage(this.message);
this.message = '';
}
ngOnDestroy(): void {
this.sub.unsubscribe();
}
}
في هذا المثال تم إنشاء خدمة (Service) مسؤولة عن إدارة اتصال WebSocket داخل أنجولار باستخدام RxJS. تم تعريف WebSocketSubject لإرسال واستقبال الرسائل بشكل تفاعلي. من خلال استخدام Subject و takeUntil، يتم التحكم في دورة حياة الاتصال وضمان إغلاقه بشكل آمن عند تدمير الخدمة.
في مكون ChatComponent، يتم التعامل مع البيانات القادمة من الخدمة بطريقة تفاعلية باستخدام الاشتراك (Subscription) على Observable يتم إرجاعه من خدمة WebSocket. عند كل رسالة جديدة، يتم تحديث حالة المكون (State) وإعادة عرض الرسائل في القالب (Template).
هذا النمط في أنجولار يعكس مبدأ "إدارة الحالة التفاعلية" (Reactive State Management) دون الحاجة إلى تمرير البيانات بين المكونات (Prop Drilling). كما يضمن عدم إعادة الرندرة غير الضرورية بفضل الفصل بين المنطق والواجهة.
من الممارسات الجيدة أيضًا استخدام ngOnDestroy لفصل الاشتراكات ومنع تسرب الذاكرة (Memory Leaks). يمثل هذا الأسلوب قاعدة أساسية لتطبيقات أنجولار المتقدمة التي تعتمد على اتصالات دائمة مثل WebSockets.
مثال عملي
typescript// مثال عملي متقدم يستخدم WebSockets لتحديث بيانات لوحة تحكم في الوقت الحقيقي
import { Component, OnInit, OnDestroy } from '@angular/core';
import { webSocket, WebSocketSubject } from 'rxjs/webSocket';
import { Subscription } from 'rxjs';
interface DashboardData {
usersOnline: number;
transactions: number;
alerts: string[];
}
@Component({
selector: 'app-dashboard',
template: ` <div class="dashboard"> <h2>لوحة تحكم مباشرة</h2> <p>المستخدمون المتصلون: {{ data?.usersOnline }}</p> <p>عدد المعاملات: {{ data?.transactions }}</p> <ul> <li *ngFor="let alert of data?.alerts">{{ alert }}</li> </ul> </div>
`
})
export class DashboardComponent implements OnInit, OnDestroy {
private socket$: WebSocketSubject<DashboardData>;
private sub!: Subscription;
data: DashboardData | null = null;
ngOnInit(): void {
this.socket$ = webSocket('wss://example.com/dashboard');
this.sub = this.socket$.subscribe({
next: (update) => (this.data = update),
error: (err) => console.error('خطأ:', err),
complete: () => console.log('تم إغلاق الاتصال.')
});
}
ngOnDestroy(): void {
this.sub.unsubscribe();
this.socket$.complete();
}
}
أفضل الممارسات في أنجولار عند العمل مع WebSockets تتضمن استخدام Observables لإدارة تدفق البيانات بشكل تفاعلي، وتقسيم المنطق بين الخدمات والمكونات لضمان القابلية لإعادة الاستخدام. من الأخطاء الشائعة تمرير البيانات عبر سلاسل طويلة من المكونات (Prop Drilling) مما يعقد الصيانة. بدلاً من ذلك، يجب الاعتماد على خدمات مشتركة (Shared Services).
كما يجب تجنب إعادة الرندرة غير الضرورية عبر الفصل بين واجهة العرض والمنطق التفاعلي باستخدام ChangeDetectionStrategy.OnPush عند الإمكان. من المهم أيضًا تجنب التلاعب المباشر بالحالة (State Mutations) واستخدام نسخ جديدة من البيانات للحفاظ على نقاء الحالة.
من ناحية الأداء، يُفضل ضغط الرسائل الكبيرة وإدارة حجم البيانات المنقولة. أما في جانب الأمان، فيجب التحقق من مصدر الاتصال (Origin) واستخدام بروتوكول آمن (wss://) لتجنب اعتراض البيانات. أخيرًا، استخدم أدوات التصحيح مثل RxJS Marbles أو DevTools لمراقبة تدفق الرسائل وضمان استقرار الاتصال.
📊 جدول مرجعي
عنصر أو مفهوم أنجولار | الوصف | مثال استخدام |
---|---|---|
WebSocketSubject | واجهة RxJS لإنشاء اتصال WebSocket تفاعلي | this.socket$ = webSocket('wss://server') |
Observable | تدفق بيانات يمكن الاشتراك فيه لإدارة الرسائل | this.socket$.subscribe(msg => console.log(msg)) |
Service | مكون مسؤول عن منطق الاتصال ومشاركة البيانات بين المكونات | ChatWebSocketService يدير الاتصال |
Component Lifecycle | دورة حياة المكون للتحكم في الاشتراكات وإدارة الموارد | ngOnInit, ngOnDestroy لإدارة الاتصال |
Change Detection | آلية تحديث واجهة المستخدم بكفاءة | ChangeDetectionStrategy.OnPush للأداء العالي |
ملخص وخطوات تالية في أنجولار:
بعد دراسة WebSockets في أنجولار، أصبح بإمكانك الآن إنشاء اتصالات لحظية وإدارة البيانات المتدفقة داخل تطبيقاتك بكفاءة. تعلمت كيفية دمج WebSockets مع المكونات والخدمات في أنجولار، إدارة دورة حياة الاتصال، وتجنب الأخطاء الشائعة المتعلقة بالأداء وإدارة الحالة.
الخطوة التالية هي استكشاف موضوعات أكثر تعقيدًا مثل التكامل مع NgRx لإدارة الحالة التفاعلية في التطبيقات الكبيرة، أو بناء أنظمة إشعارات في الوقت الحقيقي. كما يُنصح بتجربة تحسين الأداء باستخدام استراتيجيات الكشف عن التغييرات (Change Detection) المتقدمة.
لتوسيع معرفتك، استكشف موارد مثل وثائق RxJS الرسمية، وموقع Angular.io الذي يحتوي على أدلة مفصلة حول الاتصال بالـ WebSocket وإدارة البيانات التفاعلية.
🧠 اختبر معرفتك
اختبر معرفتك
تحدى نفسك مع هذا الاختبار التفاعلي واكتشف مدى فهمك للموضوع
📝 التعليمات
- اقرأ كل سؤال بعناية
- اختر أفضل إجابة لكل سؤال
- يمكنك إعادة الاختبار عدة مرات كما تريد
- سيتم عرض تقدمك في الأعلى