مقدمة: لماذا نحتاج إلى عميل HTTP في Node.js؟
في تطوير الويب الحديث، لا يمكن الاستغناء عن التفاعل مع الخدمات الخارجية. سواء كان إرسال البيانات إلى الخادم، أو الحصول على أسعار العملات، أو العمل مع REST API، أو التكامل مع المنصات السحابية — كل هذا يتطلب القدرة على إرسال طلبات HTTP. في بيئة Node.js، توجد عدة طرق لذلك: من الوحدة المدمجة http إلى المكتبات الخارجية الشائعة مثل axios و fetch الأصلي.
في هذه المقالة، سنشرح كيفية تنظيم عميل HTTP بشكل صحيح في JavaScript (Node.js)، وما هي الأدوات التي يجب اختيارها لمهام مختلفة، وكيفية تجنب الأخطاء النموذجية. ستتعلم كيفية معالجة الردود، وإدارة التزامن، وكتابة كود نظيف وقابل للصيانة.
الطرق الأساسية لإنشاء طلبات HTTP في Node.js
توفر Node.js للمطور عدة خيارات للعمل مع HTTP. سننظر في ثلاثة طرق رئيسية: الوحدة المدمجة http، ومكتبة axios، و fetch الأصلي.
1. الوحدة المدمجة http/https
الطريقة الأكثر مستوى منخفض. تمنح تحكمًا كاملاً في الطلب، ولكنها تتطلب كتابة كود أكثر. مناسبة للحالات التي تحتاج فيها إلى تقليل التبعيات أو العمل مع بروتوكولات غير قياسية.
مثال لطلب GET باستخدام الوحدة https:
const https = require('https');
function getUsers() { return new Promise((resolve, reject) => { https.get('https://jsonplaceholder.typicode.com/users', (res) => { let data = ''; res.on('data', chunk => data += chunk); res.on('end', () => resolve(JSON.parse(data))); }).on('error', reject); });}
getUsers().then(users => console.log(users[0].name));الإيجابيات: لا تبعيات خارجية، تحكم كامل.
السلبيات: كود ضخم، الحاجة إلى التغليف في Promise، إدارة يدوية للتيارات.
2. مكتبة axios
المكتبة الأكثر شيوعًا لطلبات HTTP. تعمل في كل من المتصفح و Node.js. تدعم Promise، والمعترضات (interceptors)، والتحليل التلقائي لـ JSON، وإلغاء الطلبات.
التثبيت:
npm install axiosمثال لطلب POST باستخدام axios:
const axios = require('axios');
async function createPost() { try { const response = await axios.post('https://jsonplaceholder.typicode.com/posts', { title: 'HTTP client in JavaScript', body: 'Making requests correctly', userId: 1 }); console.log('تم إنشاء المنشور:', response.data); } catch (error) { console.error('خطأ:', error.message); }}
createPost();الإيجابيات: API بسيط، معالجة تلقائية لـ JSON، معترضات، مهلات زمنية.
السلبيات: يتطلب التثبيت، حجم المكتبة (~14 كيلوبايت gzip).
3. fetch الأصلي (Node.js 18+)
بدءًا من إصدار Node.js 18، أصبح fetch دالة مدمجة. هذا يوحد الكود بين المتصفح والخادم. ومع ذلك، في الإصدارات القديمة من Node.js، ستحتاج إلى polyfill.
مثال باستخدام fetch و async/await:
async function getUser(id) { const response = await fetch(`https://jsonplaceholder.typicode.com/users/${id}`); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const user = await response.json(); return user;}
getUser(1).then(user => console.log(user.name));الإيجابيات: أصلي، لا يتطلب تثبيتًا، API حديث.
السلبيات: غير مدعوم في Node.js < 18، لا يوجد مهلة زمنية مدمجة، يتطلب فحص الحالة يدويًا.
المعالجة الصحيحة للأخطاء والمهلات الزمنية
واحدة من أكثر المشاكل شيوعًا عند العمل مع عملاء HTTP هي تجاهل معالجة الأخطاء. الشبكة غير موثوقة، قد يستجيب الخادم بخطأ 500 أو لا يستجيب على الإطلاق