البرمجة

دليل XMLHttpRequest الشامل

مقدّمة

منذ اللحظة التي أُضيف فيها مفهوم «الويب الديناميكي» إلى قاموس مطوّري الواجهة الأمامية، برز كائن XMLHttpRequest بوصفه الجسر الذي يصل صفحات HTML‑CSS الجامدة بخوادم تُغدِقها بالبيانات في الخلفية. وسواء أكانت البيانات المستردّة تُعرَّف بصيغة ‎XML، ‎JSON، ‎HTML مصغّر أم مجرّد نص خام، أتاح هذا الكائن نقلها بلا حاجة إلى إعادة تحميل الصفحة كاملة، الأمر الذي مهّد الطريق لثورة تطبيقات الويب الأحادية الصفحة (SPA) ومهّد لولادة تجارب استخدام أسرع وأكثر سلاسة.

يستعرض هذا المقال—بأسلوب تحليلي وعلمي ممتد—النشأة التاريخية لـ XMLHttpRequest، وبنيته الداخلية، وآليّة عمله، وأساليبه الرئيسة، ومعاييره الأمنيّة، ومواطن القوّة والقصور فيه مقارنةً بواجهات أحدث مثل Fetch و Axios و GraphQL. كما يتطرّق إلى أفضل الممارسات (Best Practices) في استخدامه، وأخطر زلّات الأداء والأمان التي تترصّده، وأساليب تتبّع الأخطاء وتصحيحها. يُختتم المقال بجدول مقارن يسهّل على المطوّر العربي المفاضلة بين XMLHttpRequest والبدائل الأحدث في ضوء سيناريوهات واقعيّة.


1. الجذور التاريخية وتطوّر المواصفات

1.1 البدايات في مايكروسوفت Outlook Web Access

في عام 1998 احتاج فريق Outlook Web Access إلى ميزة تحديث جزءٍ من الصفحة دون إعادة تحميلها. استُخدم مكوّن ActiveX XMLHttp على متصفّح Internet Explorer 5 لطلب موارد من الخادم بشكل خفي. ومع اتّساع انتشار الفكرة، اقتبس مجتمع الويب هذه التقنية وأُعيد تصميمها على شكل كائن أصليّ في لغة جافاسكربت تحت اسم XMLHttpRequest.

1.2 تبنّي W3C ثم WHATWG

2006: أصدرت W3C أول مسوّدة توصية للكائن، واضعة الأساس لسلوك موحَّد عبر المتصفّحات.

2012: انتقل تطوير المواصفات إلى مجموعة WHATWG الحيّة، ليتمّ دمج تحسينات مثل مستوى الاستجابة (responseType) ودعم التقدّم (progress events)، وتغذية واجهة الأحداث (EventTarget) ليتناغم مع DOM Events.


2. البنية الداخليّة للكائن

خاصية النوع وصف موجز
readyState ‎unsigned short‎ (0–4) حالة الطلب: ‎0 (إنشاء) → ‎1 (فتح) → ‎2 (إرسال) → ‎3 (تلقّي) → ‎4 (اكتمل)
status ‎unsigned short‎ كود استجابة HTTP (200، ‎404…)
responseText ‎DOMString‎ النص الخام المسترجَع (غير مفكوك ترميزًا)
responseXML ‎Document‎ شجرة ‎XML‎ مفكّكة (إذا كان نوع الاستجابة ‎XML‎ وصالح نحويًا)
responseType ‎DOMString‎ يحدّد معالجة الاستجابة (”‎، ‎’text’‎، ‎’json’‎، ‎’arraybuffer’‎، ‎’blob’‎…)
timeout ‎unsigned long‎ حدّ زمني بالميلي ثانية قبل إطلاق حدث ‎ontimeout
withCredentials ‎boolean‎ يفعِّل إرسال ملفات تعريف الارتباط (Cookies) وأروقة المصادقة عبر النطاقات

3. آليّة العمل خطوة بخطوة

  1. تهيئة الكائن

    js
    const xhr = new XMLHttpRequest();
  2. فتح قناة الاتصال

    js
    xhr.open('GET', '/api/articles', true); // true تعني غير متزامن
  3. ضبط الرؤوس الاختيارية

    js
    xhr.setRequestHeader('Accept', 'application/json');
  4. إرفاق مستمعات الحدث

    js
    xhr.onload = handleSuccess; xhr.onerror = handleFailure; xhr.ontimeout = notifySlowNetwork;
  5. إرسال الطلب

    js
    xhr.send(null); // أو send(body) لطلبات POST/PUT
  6. تلقّي الاستجابة

    عند انتقال readyState إلى 4، يصبح status جاهزًا للتحقّق، ثم تُعالج البيانات وفق responseType.


4. الأحداث الرئيسة وانعكاسها على تجربة المستخدم

  • loadstart: يتيح إظهار مؤشر التحميل.

  • progress: مهم لعرض شريط تقدّم في عمليات رفع ملفات كبيرة.

  • readystatechange: يوفّر مرونة رغم قدمه، لكن يفضَّل استخدام ‎load‎ و error‎ مباشرة لوضوحية أكبر.

  • abort: يسمح للمستخدم بإلغاء العملية لتوفير بيانات الهاتف.


5. قضايا الأمان

5.1 سياسة المصدر الموحَّد (CORS)

إنّ XMLHttpRequest يُطبّق CORS على مستوى المتصفّح. لضمان عمل الطلب العابر للنطاقات، ينبغي للخادم إرسال رأس:

arduino
Access-Control-Allow-Origin: https://client.example.com

5.2 هجمات CSRF و XSS

  • تفعيل ‎withCredentials‎ بلا ضوابط يزيد خطر CSRF.

  • حقن الاستجابة بنص HTML غير مفلتر يؤدي إلى XSS منعكسة.

  • أفضل نهج: إرسال رمز CSRF مميّز بالجلسة، واستخدام عناوين محتوى صريحة (Content‑Security‑Policy).


6. الأداء وتحسين الاستهلاك

  • Keep‑Alive: الإبقاء على اتصال ‎HTTP/1.1‎ فعّال لتقليل زمن الإعداد.

  • تقسيم البيانات (Pagination) يقلّل حجم الاستجابة.

  • تفعيل ضغط Brotli أو Gzip يُنقص عرض النطاق الترددي إلى النصف أحيانًا.

  • مراقبة شبكات الهاتف: أرفق رأس ‎Save‑Data‎ واحترمه في الخادم.


7. خطايا شائعة يجب تجنّبها

الخطأ العارض الأثر العلاج المقترح
نسيان التحقّق من ‎status معالجة استجابة ‎404‎ كأنّها ‎200‎ أعطال منطقية شرط صارم: ‎if (xhr.status === 200)
استخدام ‎eval‎ على ‎responseText‎ حقن كود تعسفي ثغرة أمنيّة خطيرة استبدل بـ ‎JSON.parse()‎ أو DOMParser
استدعاء متزامن ‎open(..., false) تجميد واجهة المستخدم تجربة سيئة اجعل ‎async‎ دائمًا ‎true‎
عدم معالجة ‎timeout دوران لانهائي في الشبكات الضعيفة استنزاف البطارية اضبط ‎xhr.timeout‎ وأضف مستمع ‎ontimeout

8. مقارنة مع واجهات أحدث

معيار XMLHttpRequest Fetch API Axios (مكتبة)
البساطة (Syntax) استدعاءات متعدّدة وعود (Promises) نظيفة ‎Promises + اعتراضات
إلغاء الطلب xhr.abort() رمز ‎AbortController ‎CancelToken‎
تدفّق ‎streaming‎ محدود ‎ReadableStream‎ أصلي يتكلّف بحلول ربط
دعم التقدّم ‎progress‎ نعم يحتاج XHR في الخلفية مدمَج
توافق قديم ممتاز منذ IE7 يحتاج Polyfill للمتصفّحات القديمة جيّد عبر ‎polyfill‎
الحجم عند الاستخدام دون مكتبات دون مكتبات ‎+ 12 KB‎ مضغوط

9. متى يظلّ XMLHttpRequest الخيار الأمثل؟

  1. التوافق مع متصفّحات قديمة في مشاريع حكومية أو أجهزة كشك تعتمد IE 11.

  2. الحاجة إلى أحداث تقدّم دقيقة في عمليات تحميل/رفع ملفات ضخمة دون الركون إلى Polyfill.

  3. مكتبات كود تاريخي ذات بنية تعتمد Observables قديمة يصعب تكييفها مع ‎Fetch‎ دون إعادة كتابة شاملة.


10. خارطة طريق للانتقال السلس إلى Fetch

  • ابدأ بتغليف استدعاءات XMLHttpRequest في دوال Promise‑based.

  • أدخل ‎AbortController‎ تدريجيًا لاستبدال ‎abort‎.

  • استبدل أحداث ‎progress‎ بمكتبة صغيرة تعتمد ‎Fetch + Streams API‎.

  • أخيرًا، احذف طبقة XHR بعد نجاح الاختبارات الشاملة.


خاتمة

لا يزال XMLHttpRequest—على الرغم من تجاوزه عقدين من العمر—أداة صلبة يعتمد عليها ملايين المواقع، ويكفي أن تنظر إلى أطر كبرى مثل jQuery لتحمل بصمته في عمقها. غير أنّ جغرافيا الويب المعاصرة تدفع المطوّر إلى تبنّي واجهات واعدة كـ Fetch ومحركات GraphQL التي تتخطّى حدود نقل الموارد إلى نماذج استعلاميّة غنيّة. بيد أنّ الفهم العميق لبنية XMLHttpRequest وآليات عمله يظلّ ضرورة تربويّة لضمان الصيانة الآمنة للتطبيقات القديمة، وتطوير حلول هجينة تراعي الأداء والأمان معًا.


المراجع

  1. WHATWG Living Standard – XMLHttpRequest (محدَّث حتى أبريل 2025).

  2. Mozilla Developer Network (MDN) – XMLHttpRequest API Documentation.