دليل شامل: استخدام Fetch API لإجراء طلبات AJAX في JavaScript
مقدمة إلى Fetch API: ثورة في طلبات AJAX
في عالم تطوير الويب الحديث، أصبحت التفاعلات غير المتزامنة مع الخوادم (AJAX) جزءًا لا يتجزأ من تجربة المستخدم السلسة. لطالما كانت واجهة XMLHttpRequest هي الأداة الرئيسية لهذه المهام، ولكن مع تطور المعايير، ظهرت واجهة Fetch API كبديل أكثر حداثة ومرونة وقوة. تُعد Fetch API واجهة برمجية قياسية لإجراء طلبات الشبكة، وهي مدعومة على نطاق واسع من قبل المتصفحات الحديثة، وتستخدم بشكل أساسي لاستدعاء واجهات برمجة التطبيقات (APIs) وجلب الموارد من الخادم.
تُبنى Fetch API على مفهوم الوعود (Promises)، مما يجعل التعامل مع العمليات غير المتزامنة أكثر وضوحًا وقابلية للقراءة، متجنبة بذلك تعقيدات “جحيم ردود النداء” (Callback Hell) التي كانت شائعة مع الطرق القديمة. في هذا الدليل، سنتعمق في كيفية استخدام Fetch API لإجراء طلبات AJAX فعالة في JavaScript.
فهم أساسيات Fetch API
تُعد الدالة fetch() هي نقطة البداية لاستخدام Fetch API. تأخذ هذه الدالة وسيطين أساسيين: مسار المورد (URL) و كائن خيارات اختياري (options). تُرجع الدالة fetch() وعدًا (Promise) يتم حله بكائن Response عند استلام استجابة من الخادم، أو يتم رفضه في حالة حدوث خطأ في الشبكة.
const promise = fetch(url, [options]);
من المهم فهم أن الوعد الذي تُرجعه fetch() يتم رفضه فقط إذا كان هناك خطأ في الشبكة (مثل عدم توفر الاتصال بالإنترنت). أما إذا تم الاتصال بالخادم واستجاب برمز حالة (status code)، حتى لو كان رمزًا يشير إلى خطأ من جانب العميل (مثل 404 Not Found) أو خطأ من جانب الخادم (مثل 500 Internal Server Error)، فإن الوعد سيتم حله بنجاح، وسيكون عليك التحقق من رمز الحالة يدويًا داخل معالج .then().
مثال على طلب GET بسيط
الطلب الافتراضي الذي تُرسله fetch() هو طلب GET. إليك مثال يوضح كيفية إجراء طلب GET بسيط وجلب البيانات بتنسيق JSON:
fetch(url)
.then(response => {
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.json();
})
.then(data => console.log(data))
.catch(err => console.error('حدث خطأ أثناء جلب البيانات:', err));
في هذا المثال:
- نستخدم
fetch(url)لبدء الطلب. - يتم استخدام
.then(response => response.json())لتحويل كائن الاستجابة (Response) إلى كائنJSON. تُرجع دالةjson()وعدًا آخر يتم حله بالبيانات المحللة. - يتم استخدام
.catch(err => console.error(err))للتعامل مع أي أخطاء قد تحدث أثناء عملية الجلب أو تحليل البيانات. - تمت إضافة التحقق من
response.okلرموز الحالة التي تشير إلى نجاح الطلب (200-299)، وفي حال عدم النجاح، يتم إلقاء خطأ ليتم التقاطه بواسطة.catch().
تخصيص الطلبات باستخدام كائن الخيارات (options)
لإرسال طلبات بخلاف GET، أو لتضمين رؤوس (headers) مخصصة، أو لإرسال نص طلب (body)، يمكنك استخدام كائن الخيارات (options) كوسيط ثانٍ للدالة fetch(). إليك بعض الخصائص الشائعة التي يمكن أن يأخذها كائن options:
method: لتحديد طريقةHTTP، مثل'GET'،'POST'،'PUT'،'DELETE'،'PATCH'.headers: كائنHeadersأو كائن عادي يحتوي على رؤوسHTTPللطلب (مثل'Content-Type').body: البيانات التي سيتم إرسالها مع الطلب (عادةً ما تكون لسجلاتPOSTأوPUT). يجب أن تكون سلسلة نصية (string) أوFormDataأوBlobأوBufferSource. غالبًا ما تستخدمJSON.stringify()لتحويل كائناتJavaScriptإلى سلاسلJSON.mode: وضعCORSللطلب، مثل'cors'(افتراضي)،'no-cors'،'same-origin'.cache: وضع التخزين المؤقت للطلب، مثل'default'،'no-cache'،'reload'.credentials: يحدد ما إذا كان يجب إرسال ملفات تعريف الارتباط (cookies) مع الطلب، مثل'omit'،'same-origin'،'include'.
مثال عملي: جلب قائمة مستودعات GitHub
يوضح هذا المثال كيفية استخدام fetch لاستدعاء واجهة برمجة تطبيقات (API) وجلب قائمة بمستودعات Git لمستخدم معين:
const url = 'https://api.github.com/users/shrutikapoor08/repos';
fetch(url)
.then(response => {
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.json();
})
.then(repos => {
const reposList = repos.map(repo => repo.name);
console.log('قائمة المستودعات:', reposList);
})
.catch(err => console.error('فشل جلب المستودعات:', err));
في هذا الكود، يتم جلب قائمة المستودعات، ثم يتم استخدام دالة map() لاستخراج أسماء المستودعات فقط وعرضها في وحدة التحكم.
إرسال طلب POST باستخدام async/await
لإرسال طلب POST، يمكن استخدام خاصية method ضمن كائن الخيارات. يمكن دمج Fetch API مع بناء جملة async/await لجعل الكود غير المتزامن يبدو وكأنه متزامن، مما يزيد من وضوحه:
async function postData(url = '', data = {}) {
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.json();
}
// مثال على الاستخدام:
const params = { id: 123, name: 'مثال بيانات' };
postData('https://api.example.com/items', params)
.then(data => console.log('البيانات المرسلة بنجاح:', data))
.catch(error => console.error('حدث خطأ أثناء إرسال البيانات:', error));
في هذا المثال:
- يتم تعريف دالة
postDataكدالةasync. - يتم استخدام
await fetch(...)لانتظار اكتمال طلب الشبكة. - يتم تحديد
method: 'POST'. - يتم تعيين
'Content-Type': 'application/json'في الرؤوس لإعلام الخادم بأن نص الطلب هوJSON. - يتم تحويل كائن البيانات
paramsإلى سلسلةJSONباستخدامJSON.stringify(params)وإرسالها كـbodyللطلب. - يتم استخدام
await response.json()لانتظار تحليل استجابةJSON.
الخلاصة التقنية
تُقدم Fetch API نقلة نوعية في كيفية تعامل مطوري الويب مع طلبات AJAX. بفضل تصميمها القائم على الوعود (Promises) ودعمها لـ async/await، أصبحت عملية إجراء طلبات الشبكة أكثر بساطة، ووضوحًا، وقابلية للصيانة مقارنة بواجهة XMLHttpRequest التقليدية. إن فهم كيفية استخدام كائن الخيارات لتخصيص الطلبات، والتعامل مع الاستجابات والأخطاء بشكل فعال، يُمكّن المطورين من بناء تطبيقات ويب حديثة وسريعة الاستجابة. تُعد Fetch API الأداة الموصى بها لإجراء جميع أنواع طلبات HTTP في JavaScript الحديثة، وتُسهم بشكل مباشر في تحسين أداء وتجربة المستخدم.