عميل HTTP بلغة JavaScript: إجراء الطلبات بشكل صحيح — من الألف إلى الياء
\nفي تطوير الويب الحديث، يعد التفاعل مع واجهات API الخارجية والخوادم مهمة روتينية ولكنها بالغة الأهمية. بغض النظر عما إذا كنت تكتب خدمة مصغرة على Node.js، أو تقوم بتحليل البيانات، أو تنشئ بوتًا، فستحتاج إلى عميل HTTP موثوق. في هذه المقالة، سنشرح كيفية إجراء طلبات HTTP بلغة JavaScript (Node.js) بشكل صحيح، وسنستعرض المكتبات الشائعة ومعالجة الأخطاء والمهلات وأفضل الممارسات.
\n\n1. الأدوات المدمجة: وحدة http و node-fetch
\nتحتوي Node.js على وحدة مدمجة http و https، لكن واجهة برمجة التطبيقات الخاصة بها منخفضة المستوى وغير ملائمة للاستخدام اليومي. لذلك، غالبًا ما يتم استخدام مكتبات التغليف.
1.1. node-fetch (الإصدار 3+)
\nبدءًا من الإصدار 18، تحتوي Node.js على دعم مدمج لـ fetch (بشكل تجريبي). للإصدارات الأقدم أو الوظائف الموسعة، استخدم الحزمة node-fetch.
// التثبيت: npm install node-fetch\nimport fetch from 'node-fetch';\n\nasync function getUsers() {\n try {\n const response = await fetch('https://jsonplaceholder.typicode.com/users');\n if (!response.ok) {\n throw new Error(`خطأ HTTP! الحالة: ${response.status}`);\n }\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error('خطأ في الطلب:', error.message);\n }\n}\n\ngetUsers();\n\n1.2. fetch المدمج (Node.js 18+)
\nيتم استخدامه بشكل مشابه لـ fetch في المتصفح:
\n// Node.js 18+ بدون حزم إضافية\nasync function postData() {\n const response = await fetch('https://api.example.com/data', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ key: 'value' })\n });\n return response.json();\n}\n\n2. Axios — المعيار الذهبي لعميل HTTP
\nAxios هي المكتبة الأكثر شيوعًا لطلبات HTTP في JavaScript. توفر واجهة سهلة الاستخدام، ودعمًا للـ Promises، والمعترضات (interceptors)، والتحويل التلقائي لـ JSON.
\n\n2.1. التثبيت وطلب GET أساسي
\n// npm install axios\nconst axios = require('axios');\n\nasync function fetchUsers() {\n try {\n const response = await axios.get('https://jsonplaceholder.typicode.com/users');\n console.log(response.data); // البيانات محللة بالفعل\n } catch (error) {\n console.error('خطأ:', error.message);\n }\n}\n\n2.2. طلب POST مع بيانات
\nasync function createUser() {\n const newUser = { name: 'إيفان', email: 'ivan@example.com' };\n const response = await axios.post('https://jsonplaceholder.typicode.com/users', newUser);\n console.log('تم إنشاء المستخدم:', response.data);\n}\n\n2.3. ضبط المهلة والرؤوس
\nالمهلة هي خيار بالغ الأهمية لمنع تعليق التطبيق:
\nasync function fetchWithTimeout() {\n try {\n const response = await axios.get('https://slow-api.example.com/data', {\n timeout: 5000, // 5 ثوانٍ\n headers: {\n 'Authorization': 'Bearer token123',\n 'Accept': 'application/json'\n }\n });\n return response.data;\n } catch (error) {\n if (error.code === 'ECONNABORTED') {\n console.error('مهلة الطلب');\n }\n }\n}\n\n3. التقنيات المتقدمة وأفضل الممارسات
\n\n3.1. معالجة الأخطاء وإعادة المحاولة (retry)
\nالشبكات غير مستقرة، لذلك من المهم تنفيذ آلية إعادة المحاولة:
\nasync function fetchWithRetry(url, retries = 3) {\n for (let i = 0; i < retries; i++) {\n try {\n const response = await axios.get(url);\n return response.data;\n } catch (error) {\n if (i === retries - 1) throw error; // المحاولة الأخيرة\n console.log(`المحاولة ${i + 1} فشلت، إعادة المحاولة بعد ${(i + 1) * 1000}ms...`);\n await new Promise(