تطوير تطبيقات الويب باستخدام Angular


الدرس: التفاعل مع خادم مع HttpClient


الصفحة السابقة
في تطبيق Angular ، غالبًا ما ستحتاج إلى إجراء استدعاءات إلى خلفية أو إلى خادم آخر - لحفظ البيانات أو تحميلها ، على سبيل المثال ، أو لإجراء حسابات أو تعديلات على البيانات التي لا تريد إجراؤها من الواجهة الأمامية. يوفر Angular خدمة تسمى   HttpClient  تسمح لك بإنشاء وتنفيذ مكالمات HTTP (التي يتم إجراؤها بواسطة AJAX - JavaScript و XML غير المتزامن ) والتفاعل مع المعلومات التي يتم إرجاعها بواسطة الخادم.

في هذا الفصل ، ستقوم باعداد خلفية (backend) باستخدام خدمة Firebase من Google . تتيح هذه الخدمة إنشاء خلفية كاملة بدون كتابة كود ، ويتضمن node الكثير من الخدمات ، بما في ذلك المصادقة وقاعدة بيانات NoSQL وتخزين الملفات. في فصل لاحق ، ستتعلم كيفية استخدام الوظائف التي يوفرها Firebase من أجل دمج الخدمة بشكل أفضل. بالنسبة لهذا الفصل ، ستستخدم ببساطة واجهة برمجة تطبيقات HTTP لفهم استخدام   HttpClient  .

جهز الخلفية


انتقل إلى  ، وأنشئ حسابًا على Google أو قم بالتصديق إذا كان لديك بالفعل ، وأنشئ مشروع Firebase جديدًا. يمكنك اعداده في بلد إقامتك ومنحه الاسم الذي تريده.
بمجرد الوصول إلى وحدة التحكم ، انتقل إلى قاعدة البيانات واختر قاعدة بيانات Realtime . لمنع مشكلة المصادقة في الوقت الراهن، انتقل إلى القسم ومجموعة "القواعد "    read  و   write  في   true ، ومن ثم نشر القواعد المعدلة:
Angular web site
ارجع إلى قسم البيانات ولاحظ عنوان URL لقاعدة البيانات ، ستحتاج إليه لتهيئة مكالمات HTTP :
Angular web site
الواجهة الخلفية جاهزة الآن ، وستتمكن من دمج   HttpClient  الأجهزة الكهربائية في تطبيقك.

أرسل إلى الواجهة الخلفية


للوصول إلى الخدمة   HttpClient ، يجب أولاً إضافة   HttpClientModule مستورد من   @angular/common/http إلى   AppModule  :  

imports: [
    BrowserModule,
    FormsModule,
    ReactiveFormsModule,
    HttpClientModule,
    RouterModule.forRoot(appRoutes)
],
ستستخدم في   HttpClient البداية لإدارة بيانات قائمة الأجهزة. لذلك سوف تضخه في   AppareilService ، بعد أن أضفت الديكور سابقًا   @Injectable()  (مستورد من   @angular/core  ) :

import { Subject } from 'rxjs/Subject';
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Injectable()
export class AppareilService {

  appareilsSubject = new Subject<any[]>();

  private appareils = [
    {
      id: 1,
      name: 'Machine à laver',
      status: 'éteint'
    },
    {
      id: 2,
      name: 'Frigo',
      status: 'allumé'
    },
    {
      id: 3,
      name: 'Ordinateur',
      status: 'éteint'
    }
  ];
  
  constructor(private httpClient: HttpClient) { }
إذا لم يكن لدى خدمتك منشئ حتى الآن ، فقم بإنشائه للحقن   HttpClient  .

ستقوم أولاً بإنشاء طريقة ستسجل المصفوفة   appareils  في قاعدة البيانات عند نقطة النهاية   /appareils  باستخدام طريقة POST :

saveAppareilsToServer() {
    this.httpClient
      .post('https://httpclient-demo.firebaseio.com/appareils.json', this.appareils)
      .subscribe(
        () => {
          console.log('Enregistrement terminé !');
        },
        (error) => {
          console.log('Erreur ! : ' + error);
        }
      );
}
حلل هذه الطريقة:
  • الطريقة   post() ، التي تجعل من الممكن إطلاق مكالمة POST ، تأخذ عنوان URL المستهدف كوسيطة أولى ، وكوسيطة ثانية نص المكالمة ، أي ما يجب إرساله إلى عنوان URL ؛
  • امتداد   .json  عنوان URL خاص بـ Firebase ، لإخباره بأنك ترسل إليه البيانات بتنسيق JSON ؛
  • الطريقة   post()  تعيد Observable - لا تستدعي من تلقاء نفسها. من خلال الاشتراك ، يتم إطلاق المكالمة ؛
  • في الطريقة   subscribe() ، تتوقع الحالة التي يعمل فيها كل شيء والحالة التي يعرض فيها الخادم خطأ.
الآن قم بإنشاء زر AppareilViewComponent لتشغيل هذه النسخة الاحتياطية (بالمناسبة ، إذا لم تكن قد قمت بذلك بالفعل ، يمكنك إزالة التنشيط المشروط للأزرار "تشغيل الكل" و "إيقاف تشغيل الكل"):

<button class="btn btn-success"
        (click)="onAllumer()">Tout allumer</button>
<button class="btn btn-danger"
        (click)="onEteindre()">Tout éteindre</button>
<button class="btn btn-primary"
        (click)="onSave()">Enregistrer les appareils</button>
onSave() {
    this.appareilService.saveAppareilsToServer();
}
احفظ كل شيء ، وانقر على الزر الذي أنشأته للتو: يجب أن تظهر لك رسالة النجاح التي تظهر في وحدة التحكم. إذا نظرت الآن إلى وحدة تحكم Firebase :
Angular web site
أنشأ Firebase عقدة جديدة أسفل   appareils  بمعرّف فريد ، وحفظ صفحتك هناك   appareils  .

ومع ذلك ، إذا نقرت على هذا الزر عدة مرات ، فسيستمر Firebase في إنشاء عقد جديدة ، وفي هذه الحالة ، ليس هذا هو السلوك الذي تريده . سيُعوض كل سجل بالكتابة فوق السجل السابق ، استخدم طريقة   put()  (لا حاجة لتغيير المُدخلات، لأن أساليب   put()  و   post()  تتخذ نفس المُدخلات الاولى) :

saveAppareilsToServer() {
    this.httpClient
      .put('https://httpclient-demo.firebaseio.com/appareils.json', this.appareils)
      .subscribe(
        () => {
          console.log('Enregistrement terminé !');
        },
        (error) => {
          console.log('Erreur ! : ' + error);
        }
      );
}
الآن عند حفظ البيانات ، تعرض وحدة تحكم Firebase العقدة التالية:
Angular web site
وبالتالي ، فأنت تعرف كيفية إرسال البيانات إلى خادم باستخدام طرق POST و PUT . بالنسبة للبقية ، ستقوم بدمج طلب GET لاسترداد ومعالجة البيانات من الخادم.

استقبال من الواجهة الخلفية


لطلب قائمة الأجهزة (المخزنة الآن في نقطة النهاية   /appareils  ) ، ستنشئ طريقة جديدة تستخدم الطريقة   get()  في   AppareilService  :

getAppareilsFromServer() {
    this.httpClient
      .get<any[]>('https://httpclient-demo.firebaseio.com/appareils.json')
      .subscribe(
        (response) => {
          this.appareils = response;
          this.emitAppareilSubject();
        },
        (error) => {
          console.log('Erreur ! : ' + error);
        }
      );
}
بالنسبة إلى   post()  و   put() ، تُرجع طريقة get () Observable يمكن ملاحظتها ، ولكن نظرًا لأنك هنا ستتلقى بيانات ، يحتاج TypeScript إلى معرفة نوعها (يُعتبر الكائن الراجع تلقائيًا كائنًا). لذلك ، في هذه الحالة المحددة ، يجب   أن تضيف  <any[]> لتقول أنك ستستقبل مصفوفة من النوع   any ، وبالتالي يمكن لـ TypeScript التعامل مع هذا الكائن كمصفوفة: إذا لم تقم بذلك ، سيخبرك TypeScript أن المصفوفة لا يمكنها ذلك و يمكن إعادة تعريفها على أنها كائن.

يمكنك الآن إفراغ صفيف   appareils  الخدمة ودمج زر في المكون مما يسمح بتشغيل الطريقة   getAppareilsFromServer()  :

<button class="btn btn-success"
        (click)="onAllumer()">Tout allumer</button>
<button class="btn btn-danger"
        (click)="onEteindre()">Tout éteindre</button>
<button class="btn btn-primary"
        (click)="onSave()">Enregistrer les appareils</button>
<button class="btn btn-primary"
        (click)="onFetch()">Récupérer les appareils</button>
onFetch() {
    this.appareilService.getAppareilsFromServer();
}
يمكنك الآن إضافة أجهزة جديدة وتغيير حالتها وحفظها ثم استرداد القائمة المحفوظة.

سيكون من الممكن أيضًا إجراء تحميل وتسجيل الأجهزة تلقائيًا (على سبيل المثال عن طريق استدعاء الطريقة   getAppareilsFromServer()  في   ngOnInit() ،    saveAppareilsToServer()   وبعد كل تعديل) ، لكني أردت أن أترك لك إمكانية تنفيذها يدويًا لرؤية النتيجة بطريقة أكثر واقعية.

في هذا الفصل ، تعلمت كيفية إجراء مكالمات إلى خادم HTTP بالخدمة   HttpClient  . لقد استخدمت الواجهة الخلفية لـ Firebase لهذا العرض التوضيحي: في الواقع ، يوفر Firebase واجهة برمجة تطبيقات أكثر مرونة بكثير من مكالمات HTTP البسيطة للاستفادة الكاملة من الخدمات المقدمة. في الفصول التالية من هذه الدورة ، ستتعلم كيفية دمج بعض خدمات Firebase في تطبيقك.