عميل HTTP في JavaScript: إجراء الطلبات بشكل صحيح في Node.js
تطوير الويب الحديث لا يمكن تصوره بدون التفاعل مع الخوادم البعيدة. سواء كان الحصول على البيانات من REST API، أو إرسال النماذج، أو تحميل الملفات — فإن طلبات HTTP تشكل أساس أي تكامل. إذا كنت تطور باستخدام Node.js، فلديك عدة أدوات قوية لإنشاء عميل HTTP. في هذه المقالة، سنشرح كيفية إجراء الطلبات بشكل صحيح: من الوحدات المدمجة إلى المكتبات الشائعة، مع التركيز على معالجة الأخطاء، المهلات الزمنية، وقابلية قراءة الكود.
سنناقش ثلاثة أساليب رئيسية: الوحدة المدمجة http/https، و fetch الحديث (المتاح في Node.js 18+) والمكتبة الأسطورية axios. لكل أسلوب ستجد أمثلة عملية وتوصيات.
1. الوحدة المدمجة http/https: الكلاسيكية
منذ البداية، تضمن Node.js الوحدات http و https للعمل مع طلبات الشبكة. هذه هي الطريقة الأكثر انخفاضاً في المستوى، والتي تمنحك تحكماً كاملاً في العملية. ومع ذلك، فهي تتطلب كوداً أكثر لمعالجة الاستجابة.
مثال على طلب GET باستخدام الوحدة https:
const https = require('https');
function getUsers() { return new Promise((resolve, reject) => { const options = { hostname: 'jsonplaceholder.typicode.com', path: '/users', method: 'GET', headers: { 'Content-Type': 'application/json' } };
const req = https.request(options, (res) => { let data = '';
// تجميع البيانات على أجزاء res.on('data', (chunk) => { data += chunk; });
// عند استلام الاستجابة بالكامل res.on('end', () => { if (res.statusCode >= 200 && res.statusCode < 300) { resolve(JSON.parse(data)); } else { reject(new Error(`HTTP Error: ${res.statusCode}`)); } }); });
// معالجة أخطاء الشبكة req.on('error', (err) => { reject(err); });
// مهلة زمنية في حالة التجميد req.setTimeout(5000, () => { req.destroy(); reject(new Error('Request timeout')); });
req.end(); });}
// الاستخدامgetUsers() .then(users => console.log('Users:', users.length)) .catch(err => console.error('Error:', err.message));المزايا:
- لا يتطلب تثبيت حزم إضافية.
- تحكم كامل في كل مرحلة من مراحل الاتصال.
العيوب:
- الكثير من الكود النمطي.
- معالجة يدوية للأجزاء وتجميع جسم الاستجابة.
- عمل غير مريح مع Promises بدون تغليف.
هذا الأسلوب مبرر إذا كنت تكتب مكتبة للعمل مع الشبكة أو تحتاج إلى أقصى أداء بدون تبعيات غير ضرورية. في الحالات الأخرى، من الأفضل استخدام حلول ذات مستوى أعلى.
2. Fetch API: المعيار الحديث
بدءاً من Node.js 18، أصبح fetch دالة مدمجة، مما جعله الأداة الرئيسية لطلبات HTTP. يعتمد على Promises وله بناء جملة نظيف وبديهي.
مثال على طلب POST باستخدام fetch:
async function createPost() { const url = 'https://jsonplaceholder.typicode.com/posts'; const newPost = { title: 'HTTP client in JavaScript', body: 'Making requests correctly', userId: 1 };
try { const response = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(newPost) });
// التحقق من حالة الاستجابة if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); }
const data = await response.json(); console.log('Created post ID:', data.id); return data; } catch (error) {