إذا كنت تقوم بتطوير تطبيق باستخدام AngularJS، فمن المحتمل أنك على دراية بمعترضات HTTP (HTTP interceptors). ومع ذلك، لم تكن معترضات HTTP هذه متاحة في Angular حتى الإصدار 4.3. في هذا البرنامج التعليمي، سنستخدم المعترضات (interceptors) في Angular لمعالجة طلبات واستجابات HTTP، ومعالجة الأخطاء.
المتطلبات الأساسية
Angular تطبيقات تستخدم Node.js كبيئة تشغيل. لإكمال هذا البرنامج التعليمي، ستحتاج إلى تثبيت Node.js على جهازك. لحسن الحظ، فإن تثبيت Node.js سهل للغاية. لدينا دليل كامل حول كيفية تثبيت Node.js على Ubuntu 18.04 هنا.
بالإضافة إلى ذلك، سيكون من المفيد لك معرفة Angular وأن تكون على دراية باستخدام Angular CLI لبناء تطبيقات Angular. سنستخدم Node v8.12.0 و npm v6.4.1.
الخطوة 1: إنشاء تطبيق Angular
بادئ ذي بدء، دعنا ننشئ تطبيق Angular جديدًا باستخدام Angular CLI. سنقوم بتسمية تطبيقنا Angular-Interceptor. قم بتشغيل الأمر أدناه لإنشاء التطبيق:
|
1 |
npx @angular/cli@7.0.6 new Angular-Interceptor |
سيُطلب منك تحديد بعض الخيارات. أدخل القيم الافتراضية وتابع:

بعد ذلك، انتقل إلى دليل التطبيق، وقم بتشغيل الأمر أدناه لبدء تشغيل التطبيق:
|
1 |
npx ng serve --open |

ثم، اعرض http://localhost:4200 في متصفحك لمشاهدة التطبيق. لقد قمت الآن بتهيئة تطبيق Angular أساسي.
الخطوة 2: تنسيق تطبيق Angular
هنا سنقوم بتنسيق تطبيق Angular الخاص بنا باستخدام Angular Material. لتثبيت Angular Material في مشروعك، قم بتشغيل الأمر أدناه:
|
1 |
npm install --save @angular/material@7.0.4 @angular/cdk@7.0.4 @angular/animations@7.0.4 |
سيؤدي هذا إلى تثبيت @angular/material, @angular/cdk، و @angular/animation في مشروعك. بعد ذلك، سنقوم بإعداد رسوم متحركة في المشروع. أضف BrowserAnimationsModule في ملف src/app/module.ts الخاص بك:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
... import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; @NgModule({ ... imports: [ ... BrowserAnimationsModule ], ... }) export class AppModule { } |
سنستخدم مكون الحوار (Dialog component) من Angular Material. لاستخدام مكون الحوار، يتعين علينا استيراد MatDialogModule في ملف src/app/app.module.ts الخاص بك:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
... import { MatDialogModule } from '@angular/material'; @NgModule({ ... imports: [ ... MatDialogModule ], ... }) export class AppModule { } |
لجعل واجهة المستخدم أكثر جاذبية، دعنا نضيف indigo-pink.css إلى ملف styles.scss الخاص بك:
|
1 |
@import "~@angular/material/prebuilt-themes/indigo-pink.css"; |
Step 3: Build Your Angular Interceptor
تحت مجلد app، سنقوم بإنشاء مجلد جديد باسم interceptor. داخل هذا المجلد الذي تم إنشاؤه حديثًا، قم بإنشاء ملف httpconfig.interceptor.ts جديد.
نحتاج إلى استيراد بعض التبعيات في ملف httpconfig.interceptor.ts لكي يعمل المعترض الخاص بنا. هذه التبعيات هي HttpInterceptor, HttpRequest, HttpResponse، و HttpHandler, HttpEvent, HttpErrorResponse.
سيبدو ملف httpconfig.interceptor.ts الخاص بنا كما يلي بعد الاستيراد:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
import { Injectable } from '@angular/core'; import { HttpInterceptor, HttpRequest, HttpResponse, HttpHandler, HttpEvent, HttpErrorResponse } from '@angular/common/http'; import { Observable, throwError } from 'rxjs'; import { map, catchError } from 'rxjs/operators'; |
بعد ذلك، قم بإنشاء فئة HttpConfigInterceptor وقم بتنفيذ الواجهة HttpInterceptor. هذا مثال:
|
1 2 3 4 5 6 7 |
@Injectable() export class HttpConfigInterceptor implements HttpInterceptor { intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { // ... } } |
أضف الكود أدناه إلى httpconfig.interceptor.ts ملف:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
... @Injectable() export class HttpConfigInterceptor implements HttpInterceptor { intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { const token: string = localStorage.getItem('token'); if (token) { request = request.clone({ headers: request.headers.set('Authorization', 'Bearer ' + token) }); } if (!request.headers.has('Content-Type')) { request = request.clone({ headers: request.headers.set('Content-Type', 'application/json') }); } request = request.clone({ headers: request.headers.set('Accept', 'application/json') }); return next.handle(request).pipe( map((event: HttpEvent<any>) => { if (event instanceof HttpResponse) { console.log('event--->>>', event); } return event; })); } } |
لكي يعمل، نحتاج إلى استيراد httpconfig.interceptor.ts في app.module.ts ملف:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
... import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http'; ... import { HttpConfigInterceptor } from './interceptor/httpconfig.interceptor'; @NgModule({ ... imports: [ ... HttpClientModule ], ... }) |
أضف HttpConfigInterceptor إلى providers. سنقوم بتعيين multi: true للتعامل مع اعتراضات متعددة:
|
1 2 3 4 5 6 7 8 9 10 |
... @NgModule({ ... providers: [ ... { provide: HTTP_INTERCEPTORS, useClass: HttpConfigInterceptor, multi: true } ], ... }) ... |
في القسم التالي، سنقوم بإنشاء الخدمة الخاصة بنا لمعالجة الأخطاء.
الخطوة 4: خدمة معالجة الأخطاء
هنا سنقوم بكتابة كود لمعالجة الأخطاء. سنحتاج إلى التقاط الأخطاء وعرضها بشكل مناسب للمستخدمين النهائيين. باختصار، فيما يلي الخطوات التي سنتبعها:
- أنشئ مجلدًا باسم error-dialog في app مجلد.
- أنشئ خدمة للأخطاء باسم errorDialogService في ملف باسم errordialog.service.ts.
- أضف الكود أدناه في errordialog.service.ts :
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
import { Injectable } from '@angular/core'; import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material'; import { ErrorDialogComponent } from './errordialog.component'; @Injectable() export class ErrorDialogService { public isDialogOpen: Boolean = false; constructor(public dialog: MatDialog) { } openDialog(data): any { if (this.isDialogOpen) { return false; } this.isDialogOpen = true; const dialogRef = this.dialog.open(ErrorDialogComponent, { width: '300px', data: data }); dialogRef.afterClosed().subscribe(result => { console.log('تم إغلاق مربع الحوار'); this.isDialogOpen = false; let animal; animal = result; }); } } |
|
1 2 3 4 5 6 7 8 9 10 11 12 |
import { Component, Inject } from '@angular/core'; import { MAT_DIALOG_DATA } from '@angular/material'; @Component({ selector: 'app-root', templateUrl: './errordialog.component.html' }) export class ErrorDialogComponent { title = 'Angular-Interceptor'; constructor(@Inject(MAT_DIALOG_DATA) public data: string) {} } |
|
1 2 3 4 5 6 7 8 9 10 |
<div> <div> <p> السبب: {{data.reason}} </p> <p> الحالة: {{data.status}} </p> </div> </div> |
باختصار، دعنا نسرد الخطوات أدناه:
- ابدأ باستيراد errordialog.service.
- بعد ذلك، سنضيف دالة البناء لـ errorDialogService.
- سنضيف أيضًا الكود لمعالجة استجابة الخطأ باستخدام catchError و throwError.
- استيراد errordialog.service و errordialog.component في AppModule.
بعد إجراء التغييرات، سيتم تعديل ملفين: app.module.ts و httpconfig.interceptor.ts:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
... import { ErrorDialogComponent } from './error-dialog/errordialog.component'; ... import { ErrorDialogService } from './error-dialog/errordialog.service'; ... @NgModule({ ... declarations: [ ... ErrorDialogComponent ], ... providers: [ ... ErrorDialogService ], entryComponents: [ErrorDialogComponent], }) |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
... import { ErrorDialogService } from '../error-dialog/errordialog.service'; ... @Injectable() export class HttpConfigInterceptor implements HttpInterceptor { constructor(public errorDialogService: ErrorDialogService) { } intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { ... return next.handle(request).pipe( map((event: HttpEvent<any>) => { if (event instanceof HttpResponse) { console.log('event--->>>', event); } return event; }), catchError((error: HttpErrorResponse) => { let data = {}; data = { reason: error && error.error && error.error.reason ? error.error.reason : '', status: error.status }; this.errorDialogService.openDialog(data); return throwError(error); })); } } |
الخطوة 5: إنشاء خدمات تجريبية
في هذه الخطوة، سنقوم بإنشاء خدمتين كعينة:
- واجهة برمجة تطبيقات تسجيل الدخول
- واجهة برمجة تطبيقات تفاصيل العميل
أنشئ مجلدًا جديدًا باسم services في المجلد src . بعد ذلك، داخل هذا المجلد المنشأ حديثًا، أنشئ ملفًا جديدًا باسم login.service.ts، وأضف دالتين:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; @Injectable() export class LoginService { constructor(private http: HttpClient) { } login(data) { data = { email: 'admin', password: 'admin' }; return this.http.post('http://localhost:3070/api/login', data); } getCustomerDetails() { return this.http.get('http://localhost:3070/customers/details'); } } |
الخطوة 6: استدعاء خدمة عميل HTTP
أخيرًا، وصلنا إلى الجزء الأخير من البرنامج التعليمي الخاص بنا. سنقوم باستدعاء خدمة HTTP الخاصة بنا من ملف app.component.ts. أضف دالتي LoginService إلى app.component.ts. قم باستدعاء واجهة برمجة تطبيقات تسجيل الدخول عند التحميل (onload) وتفاصيل العملاء (customers/details) باستخدام onclick:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
import { Component } from '@angular/core'; import { LoginService } from './services/login.service'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.scss'] }) export class AppComponent { title = 'Angular-Interceptor'; constructor(public loginService: LoginService) { this.loginService.login({}).subscribe(data => { console.log(data); }); } getCustomerDetails() { this.loginService.getCustomerDetails().subscribe((data) => { console.log('----->>>', data); }); } } |
الآن يتعين علينا إضافة عنصر واجهة مستخدم في app.component.html، حتى يتمكن المستخدم من النقر عليه:
|
1 |
<h2 (click)="getCustomerDetails()">الحصول على تفاصيل العميل</h2> |
لإنهاء العملية، ستحتاج إلى تضمين LoginService في providers في AppModule:
|
1 2 3 4 5 6 7 8 9 10 11 12 |
... import { LoginService } from './services/login.service'; ... @NgModule({ ... providers: [ ... LoginService ] ... }) |
أدناه، ستجد لقطة شاشة لمربع حوار معالج الأخطاء:

الخاتمة
في هذا البرنامج التعليمي، تعلمنا كيفية التعامل مع طلبات واستجابات HTTP باستخدام اعتراضات Angular. كما تعلمنا كيفية التعامل مع الأخطاء باستخدام مربع الحوار في Angular Material.
تستخدم تطبيقات Angular منصة Node.js كبيئة تشغيل. إذا كنت ترغب في معرفة المزيد عن Node.js وكيفية نشر تطبيقات Node.js باستخدام Docker، فراجع دليلنا كيفية نشر تطبيق Node.js (Express.js) باستخدام Docker على Ubuntu 20.04 الخاص بنا. يمكنك أيضًا مراجعة كيفية تنفيذ مهام الإنتاج على Ubuntu 20.04 باستخدام Node.js و تثبيت Node.js على CentOS 8: دليل كامل.
حوسبة سعيدة!
التعليقات
لا توجد تعليقات بعد. كن أول من يعلق.