توثيق Axios بالعربية
Axios هي مكتبة مبنية على الوعود (promises) لإجراء طلبات HTTP في متصفح الويب وفي بيئة Node.js. تتميز بواجهة بسيطة وسهلة الاستخدام، وتوفر العديد من الميزات المتقدمة التي تسهل التعامل مع واجهات برمجة التطبيقات (APIs).
المميزات الرئيسية:
إجراء طلبات من المتصفح
إرسال طلبات XMLHttpRequests من المتصفح بطريقة سلسة
إجراء طلبات من Node.js
إرسال طلبات HTTP من بيئة Node.js بنفس الطريقة
دعم الوعود
بناء كامل على Promise API مما يسهل كتابة الكود غير المتزامن
معترضات للطلبات والاستجابات
إمكانية إضافة تعديلات على الطلبات قبل إرسالها أو الاستجابات قبل معالجتها
تحويل البيانات تلقائيًا
تحويل البيانات من وإلى صيغة JSON بشكل تلقائي
إلغاء الطلبات
إلغاء الطلبات الجارية عند الحاجة
تثبيت Axios
باستخدام npm
npm install axios
هذا الأمر يقوم بتثبيت مكتبة Axios باستخدام مدير الحزم npm في مشروعك.
باستخدام yarn
yarn add axios
إذا كنت تستخدم مدير الحزم yarn، يمكنك تثبيت Axios باستخدام هذا الأمر.
باستخدام CDN
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
يمكنك أيضًا استخدام Axios مباشرة في صفحة HTML باستخدام رابط CDN. هذا مفيد للمشاريع البسيطة أو للاختبار السريع.
مثال أساسي
مثال بسيط لاستخدام Axios
// استيراد مكتبة Axios
import axios from 'axios';
// طلب GET بسيط
axios.get('https://api.example.com/users')
.then(function (response) {
// التعامل مع الاستجابة الناجحة
console.log(response.data);
})
.catch(function (error) {
// التعامل مع الخطأ
console.error(error);
})
.finally(function () {
// يتم تنفيذ هذا الكود دائمًا بعد then أو catch
console.log('طلب مكتمل');
});
شرح سطر بسطر
السطر 1-2
نستورد مكتبة Axios التي قمنا بتثبيتها من قبل. هذا السطر ضروري لاستخدام المكتبة في ملف JavaScript.
السطر 5
نقوم بإرسال طلب GET إلى الرابط 'https://api.example.com/users'. الدالة axios.get()
تعيد وعداً (Promise) يمكننا معالجته.
السطر 6-9
باستخدام الدالة then()
، نعالج الاستجابة الناجحة. كائن response
يحتوي على البيانات التي أرجعها الخادم، وهنا نقوم بعرضها في وحدة التحكم باستخدام console.log()
.
السطر 10-13
باستخدام الدالة catch()
، نعالج الأخطاء التي قد تحدث أثناء إرسال الطلب أو استقبال الاستجابة. في هذا المثال، نعرض الخطأ في وحدة التحكم.
السطر 14-17
الدالة finally()
تنفذ الكود بداخلها بغض النظر عن نجاح أو فشل الطلب. هذا مفيد لتنفيذ كود دائمًا بعد انتهاء الطلب، مثل إخفاء مؤشر التحميل.
طلبات GET
طلبات GET هي الأكثر شيوعًا للحصول على البيانات من الخادم. فيما يلي أمثلة مختلفة لاستخدام طلبات GET في Axios مع شرح تفصيلي.
طلب GET بسيط
الصيغة الأساسية
// طلب GET بسيط
axios.get('https://api.example.com/users')
.then(response => {
console.log(response.data);
})
.catch(error => {
console.error(error);
});
شرح:
هذا هو أبسط شكل لطلب GET. نقوم باستدعاء axios.get()
متبوعًا بالمسار المطلوب، ونعالج النتيجة باستخدام وعود Promise. السطر الثاني يحدد عنوان URL الذي نريد الحصول على بيانات منه، والسطور 3-5 تعالج الاستجابة الناجحة، والسطور 6-8 تعالج الأخطاء.
طلب GET مع معلمات الاستعلام (Query Parameters)
إضافة معلمات الاستعلام
// طريقة 1: تمرير معلمات الاستعلام في الكائن الثاني
axios.get('https://api.example.com/users', {
params: {
ID: 12345,
limit: 10,
page: 1,
sort: 'name'
}
})
.then(response => {
console.log(response.data);
})
.catch(error => {
console.error(error);
});
// طريقة 2: تضمين المعلمات في عنوان URL مباشرة
axios.get('https://api.example.com/users?ID=12345&limit=10&page=1&sort=name')
.then(response => {
console.log(response.data);
});
شرح:
هناك طريقتان لإضافة معلمات الاستعلام (Query Parameters):
الطريقة الأولى (السطور 1-15):
نستخدم الكائن params
داخل خيارات الطلب. تقوم Axios تلقائيًا بتحويل هذا الكائن إلى سلسلة استعلام في عنوان URL. على سبيل المثال، الكود في السطور 2-9 سيرسل طلبًا إلى https://api.example.com/users?ID=12345&limit=10&page=1&sort=name
.
الطريقة الثانية (السطور 17-21):
يمكننا أيضًا كتابة معلمات الاستعلام مباشرة في عنوان URL. هذه الطريقة أبسط لكنها أقل مرونة إذا كانت المعلمات متغيرة.
طلب GET مع رؤوس مخصصة (Custom Headers)
إضافة رؤوس مخصصة
axios.get('https://api.example.com/secure-data', {
headers: {
'Authorization': 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...',
'Accept': 'application/json',
'x-api-key': 'abcdef123456',
'Content-Type': 'application/json'
}
})
.then(response => {
console.log(response.data);
})
.catch(error => {
if (error.response) {
// الخادم استجاب برمز حالة ليس في نطاق 2xx
console.error('Status:', error.response.status);
} else {
console.error('Error:', error.message);
}
});
شرح:
السطور 1-8:
نقوم بإرسال طلب GET مع إضافة رؤوس مخصصة باستخدام خاصية headers
. الرؤوس المخصصة مهمة للتحقق من الهوية (السطر 3)، أو تحديد نوع المحتوى المقبول (السطر 4)، أو إرسال مفاتيح API (السطر 5).
السطور 13-18:
هنا نقوم بالتعامل مع الخطأ بطريقة أكثر تفصيلًا. خاصية error.response
متوفرة إذا استجاب الخادم بكود حالة خارج النطاق 2xx (مثل 404 أو 500). في هذه الحالة، يمكننا الوصول إلى error.response.status
لمعرفة كود الحالة.
طلبات POST
تُستخدم طلبات POST لإرسال بيانات إلى الخادم لإنشاء أو تحديث الموارد. فيما يلي أمثلة مختلفة لاستخدام طلبات POST في Axios.
طلب POST بسيط مع بيانات JSON
إرسال بيانات JSON
const userData = {
firstName: 'أحمد',
lastName: 'محمد',
email: '[email protected]',
age: 28,
active: true
};
axios.post('https://api.example.com/users', userData)
.then(response => {
console.log('تم إنشاء المستخدم بنجاح!');
console.log('ID الجديد:', response.data.id);
})
.catch(error => {
console.error('خطأ في إنشاء المستخدم:', error);
});
شرح:
السطور 1-7:
نقوم بإنشاء كائن JavaScript يحتوي على البيانات التي نريد إرسالها في طلب POST. هذا الكائن سيتم تحويله تلقائيًا إلى JSON بواسطة Axios.
السطر 9:
نستخدم دالة axios.post()
التي تأخذ معلمتين: عنوان URL وبيانات الطلب. Axios يقوم تلقائيًا بضبط رأس Content-Type
إلى application/json
ويحول الكائن إلى سلسلة JSON.
السطور 10-13:
في حالة نجاح الطلب، نطبع رسالة نجاح ونعرض معرف المستخدم الجديد الذي أرجعه الخادم. عادة ما يرجع الخادم بيانات جديدة أو محدثة في استجابة طلب POST.
السطور 14-16:
نتعامل مع أي خطأ قد يحدث في أثناء العملية، مثل خطأ اتصال بالشبكة أو رد من الخادم برمز حالة غير ناجح.
طلب POST مع خيارات إضافية
إرسال بيانات مع خيارات متقدمة
axios.post('https://api.example.com/articles', {
title: 'مقال جديد حول Axios',
content: 'محتوى المقال...',
tags: ['javascript', 'axios', 'http'],
published: true
}, {
headers: {
'Authorization': 'Bearer TOKEN_HERE',
'Content-Type': 'application/json'
},
timeout: 5000, // الحد الأقصى للانتظار هو 5 ثوانٍ
withCredentials: true, // إرسال ملفات تعريف الارتباط مع الطلب
})
.then(response => {
console.log('تم إنشاء المقال:', response.data);
})
.catch(error => {
if (error.code === 'ECONNABORTED') {
console.error('انتهت مهلة الطلب!');
} else {
console.error('خطأ:', error.message);
}
});
شرح:
السطور 1-5:
بيانات المقال التي نريد إرسالها في جسم الطلب.
السطور 6-12:
الوسيط الثالث هو كائن التكوين الذي يحتوي على خيارات متقدمة:
headers
: رؤوس HTTP مخصصة مثل رمز المصادقة ونوع المحتوى.timeout
: الحد الأقصى للوقت المسموح به للطلب بالميللي ثانية. إذا تجاوز الطلب هذه المدة، سيتم إلغاؤه تلقائيًا.withCredentials
: إذا كانتtrue
، سيتم إرسال ملفات تعريف الارتباط (cookies) مع الطلبات عبر المجالات (cross-domain).
السطور 17-22:
معالجة خاصة لحالة انتهاء المهلة. عند انتهاء مهلة الطلب، يضبط Axios رمز الخطأ إلى 'ECONNABORTED'
.
طلب POST مع بيانات النموذج (Form Data)
إرسال بيانات النموذج
// طريقة 1: استخدام FormData API
const formData = new FormData();
formData.append('userName', 'علي');
formData.append('userEmail', '[email protected]');
formData.append('avatar', fileInput.files[0]); // إضافة ملف
axios.post('https://api.example.com/profile', formData, {
headers: {
'Content-Type': 'multipart/form-data' // اختياري: Axios يضبط هذا تلقائيًا
}
})
.then(response => console.log(response.data))
.catch(error => console.error(error));
// طريقة 2: استخدام URLSearchParams لبيانات x-www-form-urlencoded
const params = new URLSearchParams();
params.append('userName', 'علي');
params.append('userEmail', '[email protected]');
axios.post('https://api.example.com/profile', params)
.then(response => console.log(response.data));
شرح:
الطريقة الأولى (السطور 1-13):
استخدام FormData
لإرسال بيانات بتنسيق multipart/form-data
، وهو مفيد بشكل خاص عند إرسال الملفات. نقوم بإنشاء كائن FormData
وإضافة الحقول إليه باستخدام طريقة append
. ملاحظة أن Axios يتعرف تلقائيًا على كائن FormData
ويضبط رأس Content-Type
المناسب.
الطريقة الثانية (السطور 15-21):
استخدام URLSearchParams
لإرسال بيانات بتنسيق application/x-www-form-urlencoded
، وهو التنسيق المستخدم في نماذج HTML التقليدية. يقوم Axios تلقائيًا بضبط رأس Content-Type
إلى application/x-www-form-urlencoded
عند اكتشاف كائن URLSearchParams
.
إعدادات الطلب
يقدم Axios مجموعة شاملة من خيارات التكوين لضبط سلوك الطلبات. فيما يلي أهم الخيارات المتاحة.
كائن التكوين الكامل
const options = {
// الرابط الذي سيتم إرسال الطلب إليه
url: 'https://api.example.com/data',
// طريقة الطلب
method: 'post', // 'get', 'post', 'put', 'delete', 'patch', 'options'
// رؤوس HTTP
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer token123'
},
// بيانات ترسل في جسم الطلب
data: {
firstName: 'سمير',
lastName: 'علي'
},
// معلمات الاستعلام في عنوان URL
params: {
page: 1,
limit: 10
},
// وقت الانتظار قبل إلغاء الطلب (بالميللي ثانية)
timeout: 3000,
// إرسال ملفات تعريف الارتباط مع الطلبات عبر المجالات
withCredentials: false,
// دوال معالجة البيانات قبل الإرسال أو بعد الاستقبال
transformRequest: [(data, headers) => {
// تحويل البيانات قبل إرسالها
return data;
}],
transformResponse: [(data) => {
// تحويل البيانات عند استلامها
return data;
}],
// دالة للتحقق من صحة رمز الحالة
validateStatus: (status) => {
return status >= 200 && status < 300; // افتراضي
},
// ملف تعريف Proxy
proxy: {
host: '127.0.0.1',
port: 9000
},
// إلغاء الطلب باستخدام رمز إلغاء
cancelToken: new axios.CancelToken(cancel => {
// دالة الإلغاء
}),
// تتبع إعادة التوجيه
maxRedirects: 5,
// نوع البيانات المتوقع من الاستجابة
responseType: 'json', // 'arraybuffer', 'document', 'json', 'text', 'stream'
// الرابط الأساسي الذي سيتم إلحاق عنوان URL به
baseURL: 'https://api.example.com/'
};
// استخدام كائن الإعدادات
axios(options).then(response => console.log(response.data));
خيارات أساسية
url
عنوان URL الذي سيتم إرسال الطلب إليه.
method
طريقة HTTP: 'get' (افتراضي)، 'post'، 'put'، 'delete'، إلخ.
baseURL
عنوان URL أساسي يتم إلحاق عنوان URL النسبي للطلب به.
headers
كائن يحتوي على رؤوس HTTP المخصصة المراد إرسالها.
params
كائن يحتوي على معلمات الاستعلام التي سيتم إضافتها إلى URL.
data
البيانات المراد إرسالها في جسم الطلب.
خيارات متقدمة
timeout
وقت الانتظار بالميللي ثانية قبل إلغاء الطلب.
withCredentials
إذا كانت قيمته true، سيتم إرسال ملفات تعريف الارتباط (cookies) مع الطلبات عبر المجالات.
responseType
نوع البيانات المتوقع من الاستجابة: 'json'، 'text'، 'blob'، 'arraybuffer'، إلخ.
validateStatus
دالة تحدد ما إذا كان يجب حل أو رفض الوعد لرمز حالة HTTP معين.
cancelToken
رمز يمكن استخدامه لإلغاء الطلب.
transformRequest / transformResponse
دوال للتحكم في كيفية تحويل البيانات قبل الإرسال أو بعد الاستقبال.
هيكل الاستجابة
عند نجاح الطلب، تحتوي استجابة Axios على معلومات مفصلة عن الاستجابة من الخادم. فيما يلي هيكل كائن الاستجابة.
هيكل كائن الاستجابة
axios.get('https://api.example.com/users/1')
.then(response => {
console.log(response.data); // البيانات التي أرجعها الخادم
console.log(response.status); // رمز الحالة HTTP (مثل 200، 201، إلخ)
console.log(response.statusText); // رسالة الحالة HTTP (مثل "OK"، "Created")
console.log(response.headers); // كائن يحتوي على رؤوس HTTP للاستجابة
console.log(response.config); // إعدادات الطلب التي تم استخدامها
console.log(response.request); // كائن الطلب الذي ولّد هذه الاستجابة
})
.catch(error => {
console.error(error);
});
تفاصيل كائن الاستجابة
response.data
البيانات الفعلية التي أرجعها الخادم. هذا هو جسم الاستجابة، وقد يكون كائن JavaScript (إذا كان التنسيق JSON)، أو سلسلة نصية، أو ArrayBuffer، إلخ، اعتمادًا على responseType
.
response.status
رمز الحالة HTTP، مثل 200 للنجاح، 201 للإنشاء، 404 لعدم العثور، إلخ.
response.statusText
النص المرتبط برمز الحالة HTTP، مثل "OK" للرمز 200، أو "Created" للرمز 201.
response.headers
كائن يحتوي على جميع رؤوس HTTP للاستجابة. يمكن الوصول إليها بطريقة غير حساسة لحالة الأحرف.
response.config
كائن التكوين الكامل الذي تم استخدامه للطلب. يفيد هذا في تصحيح الأخطاء أو إعادة إرسال الطلب.
response.request
كائن الطلب الذي ولّد هذه الاستجابة. في بيئة المتصفح، هذا هو كائن XMLHttpRequest؛ وفي Node.js، يكون كائن http.ClientRequest.
معالجة الأخطاء
تعامل Axios مع الأخطاء بطريقة منظمة ومفيدة. عند حدوث خطأ، يتم رفض الوعد (Promise) وإرسال كائن خطأ يحتوي على معلومات مفصلة.
معالجة الأخطاء الشاملة
axios.get('https://api.example.com/data')
.then(response => {
console.log('بيانات ناجحة:', response.data);
})
.catch(error => {
// معالجة أخطاء الاستجابة (الخادم استجاب برمز حالة خارج نطاق 2xx)
if (error.response) {
console.error('خطأ استجابة من الخادم:');
console.error('رمز الحالة:', error.response.status);
console.error('رسالة الحالة:', error.response.statusText);
console.error('البيانات:', error.response.data);
console.error('الرؤوس:', error.response.headers);
// معالجات خاصة برموز حالة معينة
switch (error.response.status) {
case 400:
console.error('طلب غير صالح');
break;
case 401:
console.error('غير مصرّح له');
// إعادة توجيه المستخدم إلى صفحة تسجيل الدخول
break;
case 404:
console.error('المورد غير موجود');
break;
case 500:
console.error('خطأ في الخادم');
break;
default:
console.error('خطأ غير متوقع');
}
}
// معالجة أخطاء الطلب (لم يتم إرسال الطلب أبدًا)
else if (error.request) {
console.error('خطأ في الطلب: لم يتم تلقي استجابة');
console.error(error.request);
}
// خطأ في إعداد الطلب
else {
console.error('خطأ في إعداد الطلب:', error.message);
}
// معلومات إضافية
console.error('تكوين الطلب:', error.config);
// إذا كان الخطأ هو انتهاء المهلة
if (error.code === 'ECONNABORTED') {
console.error('انتهت مهلة الطلب');
}
// إذا كان الخطأ بسبب إلغاء الطلب
if (axios.isCancel(error)) {
console.error('تم إلغاء الطلب:', error.message);
}
});
أنواع الأخطاء
أخطاء الاستجابة (error.response)
تحدث عندما يستجيب الخادم برمز حالة خارج نطاق 2xx. في هذه الحالة، تحتوي خاصية error.response
على كائن الاستجابة من الخادم، مما يسمح بالوصول إلى error.response.status
و error.response.data
وغيرها.
أخطاء الطلب (error.request)
تحدث عندما يتم إنشاء الطلب ولكن لم يتم تلقي استجابة. هذا يحدث غالبًا بسبب مشاكل في الشبكة، أو الخادم غير متاح، أو انتهاء المهلة الزمنية. error.request
هو كائن XMLHttpRequest في المتصفح، أو كائن http.ClientRequest في Node.js.
أخطاء الإعداد
تحدث عندما يكون هناك مشكلة في إعداد الطلب (مثل URL غير صالح). في هذه الحالة، error.message
تحتوي على رسالة الخطأ.
أخطاء انتهاء المهلة
عند انتهاء مهلة الطلب المحددة بواسطة timeout
، يتم تعيين error.code
إلى 'ECONNABORTED'
.
أخطاء الإلغاء
عند إلغاء الطلب باستخدام cancelToken
، يمكن التحقق من ذلك باستخدام axios.isCancel(error)
.
المعترضات (Interceptors)
معترضات Axios هي آليات قوية تسمح باعتراض الطلبات أو الاستجابات قبل معالجتها. هذا مفيد لتنفيذ منطق متكرر مثل إضافة رمز مصادقة، تسجيل الطلبات، أو معالجة الأخطاء بطريقة موحدة.
إعداد واستخدام المعترضات
// إضافة معترض طلب
const requestInterceptor = axios.interceptors.request.use(
// دالة تنفذ عند نجاح الطلب
config => {
// إضافة رمز مصادقة إلى الرؤوس
const token = localStorage.getItem('token');
if (token) {
config.headers['Authorization'] = `Bearer ${token}`;
}
// إضافة طابع زمني لمنع التخزين المؤقت
config.params = config.params || {};
config.params['_t'] = Date.now();
console.log('إرسال طلب إلى:', config.url);
// يجب أن تعيد الدالة كائن التكوين
return config;
},
// دالة تنفذ عند حدوث خطأ
error => {
console.error('خطأ قبل إرسال الطلب:', error);
// يجب أن تعيد الدالة وعداً مرفوضاً
return Promise.reject(error);
}
);
// إضافة معترض استجابة
const responseInterceptor = axios.interceptors.response.use(
// دالة تنفذ عندما تكون الاستجابة ناجحة
response => {
console.log('استجابة ناجحة من:', response.config.url);
// يمكنك تعديل بيانات الاستجابة هنا
if (response.data.timestamps) {
// تحويل الطوابع الزمنية إلى كائنات Date
response.data.timestamps = response.data.timestamps.map(ts => new Date(ts));
}
// يجب أن تعيد الدالة كائن الاستجابة
return response;
},
// دالة تنفذ عندما تفشل الاستجابة
error => {
if (error.response) {
// معالجة أخطاء محددة
if (error.response.status === 401) {
console.error('خطأ في المصادقة، جاري تسجيل الخروج...');
localStorage.removeItem('token');
window.location.href = '/login';
} else if (error.response.status === 403) {
console.error('ليس لديك صلاحيات كافية للوصول إلى هذا المورد');
}
}
// يجب أن تعيد الدالة وعداً مرفوضاً
return Promise.reject(error);
}
);
// إزالة معترض (عند الحاجة)
axios.interceptors.request.eject(requestInterceptor);
axios.interceptors.response.eject(responseInterceptor);
شرح المعترضات
معترضات الطلب
تسمح لك باعتراض الطلب قبل إرساله. تستلم دالة النجاح كائن config
الذي يمكنك تعديله قبل إرسال الطلب. هذا مفيد لإضافة رؤوس مثل رموز المصادقة (السطور 5-9)، أو إضافة معلمات استعلام (السطور 11-13). يجب دائمًا أن تعيد دالة النجاح كائن config
والفشل وعداً مرفوضاً.
معترضات الاستجابة
تسمح لك باعتراض الاستجابة قبل وصولها إلى دالة then
. تستلم دالة النجاح كائن response
الذي يمكنك تعديله. هذا مفيد لتنفيذ منطق متكرر مثل تحويل البيانات (السطور 33-36) أو تسجيل الاستجابات. يمكنك أيضًا معالجة أخطاء محددة بشكل موحد، مثل معالجة أخطاء المصادقة (السطور 43-46).
إزالة المعترضات
يمكنك إزالة معترض باستخدام طريقة eject
مع معرف المعترض الذي تم إرجاعه عند إضافة المعترض (السطران 57-58).
نصيحة مهمة:
المعترضات مفيدة جدًا للتعامل مع الحالات المتكررة في تطبيقك، مثل:
- إضافة رموز المصادقة تلقائيًا إلى جميع الطلبات
- تسجيل الطلبات والاستجابات لأغراض تصحيح الأخطاء
- إظهار/إخفاء مؤشرات التحميل تلقائيًا
- التعامل مع أخطاء محددة بطريقة موحدة
- تحويل البيانات قبل استخدامها في التطبيق
إلغاء الطلبات
يوفر Axios طريقة لإلغاء الطلبات الجارية، وهي ميزة مفيدة لتحسين تجربة المستخدم وتوفير موارد الشبكة. يمكنك إلغاء الطلبات باستخدام إحدى طريقتين: CancelToken (الطريقة القديمة) أو AbortController (الطريقة الحديثة).
الطريقة 1: باستخدام AbortController (الطريقة الموصى بها)
// إنشاء كائن AbortController
const controller = new AbortController();
// الحصول على إشارة من المتحكم
const signal = controller.signal;
// إرسال طلب مع الإشارة
axios.get('https://api.example.com/data', {
signal: signal
})
.then(response => {
console.log('تم استلام البيانات:', response.data);
})
.catch(error => {
if (axios.isCancel(error)) {
console.log('الطلب تم إلغاؤه:', error.message);
} else {
console.error('حدث خطأ:', error);
}
});
// في مكان آخر في التطبيق، إلغاء الطلب عند الحاجة
controller.abort(); // سيؤدي هذا إلى إلغاء الطلب
الطريقة 2: باستخدام CancelToken (النهج القديم)
// إنشاء مصدر إلغاء
const CancelToken = axios.CancelToken;
const source = CancelToken.source();
// إرسال طلب مع رمز إلغاء
axios.get('https://api.example.com/data', {
cancelToken: source.token
})
.then(response => {
console.log('تم استلام البيانات:', response.data);
})
.catch(error => {
if (axios.isCancel(error)) {
console.log('الطلب تم إلغاؤه:', error.message);
} else {
console.error('حدث خطأ:', error);
}
});
// في مكان آخر في التطبيق، إلغاء الطلب عند الحاجة
source.cancel('تم إلغاء الطلب بواسطة المستخدم');
حالات استخدام إلغاء الطلب
البحث في الوقت الفعلي
عندما يكتب المستخدم في حقل البحث، قد ترغب في إلغاء طلبات البحث السابقة قبل إرسال طلب جديد، لتجنب تداخل النتائج وتوفير موارد الشبكة.
التنقل بين الصفحات
عندما ينتقل المستخدم من صفحة إلى أخرى قبل اكتمال طلب البيانات، يمكنك إلغاء الطلب غير المكتمل لتجنب تحديثات حالة غير ضرورية.
طلبات تستغرق وقتًا طويلاً
عندما يطلب المستخدم بيانات كبيرة، قد ترغب في توفير زر "إلغاء" ليتمكن المستخدم من التراجع إذا تغير رأيه أو إذا كان الطلب يستغرق وقتًا طويلاً.
تنفيذ مهلة مخصصة
يمكنك تنفيذ منطق مهلة مخصص باستخدام setTimeout
وإلغاء الطلب إذا استغرق وقتًا أطول من المتوقع.
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 5000); // إلغاء بعد 5 ثوانٍ
axios.get('/api/data', { signal: controller.signal })
.then(response => {
clearTimeout(timeoutId); // إلغاء المهلة إذا نجح الطلب
// معالجة الاستجابة
})
.catch(error => {
// معالجة الخطأ
});
إنشاء كائنات Axios
يمكنك إنشاء نسخ مخصصة من Axios مع إعدادات افتراضية محددة مسبقًا. هذا مفيد عند التعامل مع واجهات برمجة متعددة أو عند الحاجة إلى تكوينات مختلفة لأجزاء مختلفة من تطبيقك.
إنشاء نسخة مخصصة من Axios
// api.js - ملف منفصل لتكوين Axios
import axios from 'axios';
// إنشاء نسخة مخصصة من Axios
const mainApi = axios.create({
baseURL: 'https://api.mainserver.com/v1',
timeout: 5000,
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
}
});
// إضافة معترضات إلى النسخة المخصصة
mainApi.interceptors.request.use(config => {
const token = localStorage.getItem('main_api_token');
if (token) {
config.headers['Authorization'] = `Bearer ${token}`;
}
return config;
});
// إنشاء نسخة ثانية مخصصة لواجهة برمجة مختلفة
const analyticsApi = axios.create({
baseURL: 'https://analytics.company.com/api',
timeout: 10000,
headers: {
'X-API-KEY': 'analytics_api_key_here'
}
});
// تصدير النسخ المخصصة لاستخدامها في ملفات أخرى
export { mainApi, analyticsApi };
// ------------------------------------------
// users.js - استخدام النسخة المخصصة
import { mainApi } from './api';
// استخدام النسخة المخصصة من Axios
const getUsers = () => {
return mainApi.get('/users');
};
const createUser = (userData) => {
return mainApi.post('/users', userData);
};
// ------------------------------------------
// analytics.js - استخدام النسخة الثانية
import { analyticsApi } from './api';
const trackEvent = (event) => {
return analyticsApi.post('/events', event);
};
مزايا استخدام نسخ Axios المخصصة
تنظيم الكود
يمكنك فصل التكوينات المختلفة لواجهات البرمجة المختلفة في نسخ منفصلة، مما يجعل الكود أكثر تنظيمًا وأسهل للصيانة (السطور 5-12 و 23-29).
تقليل التكرار
بدلاً من تكرار نفس الإعدادات (مثل URL الأساسي ورؤوس الطلب) في كل طلب، يمكنك تعيينها مرة واحدة في تكوين النسخة المخصصة (السطر 6).
معترضات محددة
كل نسخة يمكن أن يكون لها معترضاتها الخاصة، مما يسمح بمنطق مختلف لخدمات مختلفة (السطور 14-21).
اختبار أسهل
يمكنك استبدال نسخ Axios بسهولة أثناء الاختبار باستخدام النماذج الوهمية.
أفضل الممارسات:
- قم بإنشاء ملف منفصل (مثل
api.js
) لتكوين نسخ Axios وتصديرها - استخدم نسخًا مختلفة لخدمات مختلفة (API الرئيسي، تحليلات البيانات، خدمات الطرف الثالث)
- اجمع دوال الطلبات المتعلقة في وحدات منفصلة أو خدمات (مثل
users.js
) - اجعل دوال الطلبات تعيد كائن الوعد مباشرة حتى يمكن للمستخدمين استخدام
then
وcatch
استخدام Async/Await
Axios يعمل بشكل رائع مع async/await
، وهي طريقة حديثة ونظيفة للتعامل مع العمليات غير المتزامنة في JavaScript. استخدام async/await
مع Axios يجعل الكود أكثر وضوحًا ويسهل قراءته وصيانته.
استخدام Async/Await مع Axios
// استخدام async/await لطلب بسيط
async function fetchUserData(userId) {
try {
// انتظار اكتمال الطلب
const response = await axios.get(`https://api.example.com/users/${userId}`);
// في هذه المرحلة، تم استلام البيانات
console.log('بيانات المستخدم:', response.data);
return response.data;
} catch (error) {
// معالجة الأخطاء
console.error('خطأ في جلب بيانات المستخدم:', error.message);
throw error; // إعادة رمي الخطأ للمعالجة في مكان آخر
}
}
// طلبات متعددة متتالية
async function fetchUserWithPosts(userId) {
try {
// الطلب الأول: الحصول على بيانات المستخدم
const userResponse = await axios.get(`https://api.example.com/users/${userId}`);
const user = userResponse.data;
// الطلب الثاني: الحصول على منشورات المستخدم
const postsResponse = await axios.get(`https://api.example.com/users/${userId}/posts`);
const posts = postsResponse.data;
// دمج البيانات
return {
user,
posts
};
} catch (error) {
console.error('خطأ في جلب بيانات المستخدم والمنشورات:', error.message);
throw error;
}
}
// طلبات متوازية باستخدام Promise.all
async function fetchDashboardData(userId) {
try {
// إرسال عدة طلبات في نفس الوقت
const [user, posts, analytics] = await Promise.all([
axios.get(`https://api.example.com/users/${userId}`),
axios.get(`https://api.example.com/users/${userId}/posts`),
axios.get(`https://api.example.com/users/${userId}/analytics`)
]);
// استخدام النتائج
return {
user: user.data,
posts: posts.data,
analytics: analytics.data
};
} catch (error) {
console.error('خطأ في جلب بيانات لوحة المعلومات:', error.message);
throw error;
}
}
// استدعاء الدوال الغير متزامنة
async function main() {
try {
const userData = await fetchUserData(123);
const userWithPosts = await fetchUserWithPosts(123);
const dashboardData = await fetchDashboardData(123);
console.log('تم تحميل جميع البيانات بنجاح!');
} catch (error) {
console.error('فشل تحميل البيانات:', error);
}
}
// تنفيذ الدالة الرئيسية
main();
أنماط استخدام Async/Await مع Axios
طلب بسيط (السطور 1-15)
استخدام async/await
مع try/catch
لإجراء طلب واحد بطريقة نظيفة. الكلمة الأساسية await
توقف تنفيذ الدالة حتى يكتمل الوعد، ويسمح لك باستخدام نمط برمجة أكثر تسلسلية.
طلبات متتالية (السطور 17-35)
إرسال طلب ثانٍ يعتمد على نتائج الطلب الأول. هذا نمط شائع عندما تحتاج إلى بيانات من الطلب الأول لإجراء الطلب الثاني. باستخدام async/await
، يصبح هذا النمط واضحًا ومباشرًا.
طلبات متوازية (السطور 37-55)
استخدام Promise.all
مع await
لإرسال عدة طلبات في نفس الوقت وانتظار اكتمالها جميعًا. هذا يحسن الأداء عندما تكون الطلبات مستقلة عن بعضها، حيث يتم تنفيذها بالتوازي بدلاً من التتابع.
دالة رئيسية (السطور 57-69)
استخدام async/await
لاستدعاء عدة دوال غير متزامنة من دالة رئيسية. هذا النمط مفيد لتنظيم تدفق التطبيق وإدارة الأخطاء بشكل مركزي.
فوائد استخدام Async/Await مع Axios:
- كود أكثر نظافة وأسهل للقراءة مقارنة بسلاسل
then/catch
- معالجة أخطاء أكثر بداهة باستخدام
try/catch
- سهولة كتابة عمليات متسلسلة تعتمد على بعضها البعض
- دعم أفضل للتصحيح، حيث تظهر أخطاء الوقت الفعلي في المكان المناسب في الشفرة
- سهولة دمجها مع وحدات أخرى قائمة على الوعود مثل React Hooks أو Redux Thunk
معلمات الرابط
هناك العديد من الطرق للتعامل مع معلمات URL في Axios، سواء كانت معلمات استعلام (query parameters) أو معلمات مسار (path parameters). سنستعرض الطرق المختلفة وأفضل الممارسات.
معلمات الاستعلام والمسار
// 1. معلمات الاستعلام (Query Parameters) باستخدام خاصية params
axios.get('https://api.example.com/users', {
params: {
page: 1,
limit: 10,
sort: 'name',
order: 'asc',
search: 'محمد'
}
})
.then(response => console.log(response.data));
// الناتج: https://api.example.com/users?page=1&limit=10&sort=name&order=asc&search=محمد
// 2. معلمات المسار (Path Parameters) باستخدام دمج السلاسل النصية
const userId = 123;
axios.get(`https://api.example.com/users/${userId}`)
.then(response => console.log(response.data));
// الناتج: https://api.example.com/users/123
// 3. معلمات الاستعلام مع مصفوفات
axios.get('https://api.example.com/products', {
params: {
category: ['electronics', 'computers'],
tags: ['sale', 'new']
},
// تمكين السماح بتكرار المعلمات للمصفوفات
paramsSerializer: params => {
return Object.entries(params).flatMap(([key, values]) => {
if (Array.isArray(values)) {
return values.map(value => `${key}=${value}`).join('&');
}
return `${key}=${values}`;
}).join('&');
}
})
.then(response => console.log(response.data));
// الناتج: https://api.example.com/products?category=electronics&category=computers&tags=sale&tags=new
// 4. الجمع بين معلمات المسار ومعلمات الاستعلام
const userId = 123;
const orderParams = {
status: 'completed',
from: '2023-01-01',
to: '2023-12-31'
};
axios.get(`https://api.example.com/users/${userId}/orders`, {
params: orderParams
})
.then(response => console.log(response.data));
// الناتج: https://api.example.com/users/123/orders?status=completed&from=2023-01-01&to=2023-12-31
// 5. معلمات استعلام معقدة مع URLSearchParams
const params = new URLSearchParams();
params.append('page', 1);
params.append('sort', 'name');
params.append('filter[]', 'active');
params.append('filter[]', 'verified');
axios.get('https://api.example.com/users', { params })
.then(response => console.log(response.data));
// الناتج: https://api.example.com/users?page=1&sort=name&filter[]=active&filter[]=verified
شرح طرق استخدام معلمات URL
1. معلمات الاستعلام (Query Parameters)
استخدام خاصية params
في كائن الخيارات هي الطريقة المفضلة لإضافة معلمات الاستعلام (السطور 1-11). تقوم Axios تلقائيًا بتشفير القيم وإضافتها إلى عنوان URL. هذه الطريقة أكثر أمانًا وأنظف من إضافة المعلمات يدويًا.
2. معلمات المسار (Path Parameters)
استخدام القوالب النصية (template literals) لدمج المتغيرات في المسار (السطور 14-17). هذه طريقة قياسية في JavaScript وتعمل بشكل جيد مع Axios. تأكد من معالجة المتغيرات بشكل صحيح لتجنب ثغرات أمنية.
3. معلمات الاستعلام مع مصفوفات
عند الحاجة إلى تمرير مصفوفات كمعلمات استعلام (السطور 19-35)، يمكنك استخدام paramsSerializer
لتخصيص كيفية تحويل المعلمات إلى سلسلة نصية. هذا مفيد عندما تتعامل مع واجهات برمجة تتطلب تنسيق محدد لمعلمات المصفوفة.
4. الجمع بين المسار ومعلمات الاستعلام
غالبًا ما تحتاج إلى الجمع بين معلمات المسار ومعلمات الاستعلام (السطور 37-47). يمكنك استخدام القوالب النصية لبناء المسار الأساسي، ثم إضافة معلمات الاستعلام باستخدام خاصية params
.
5. استخدام URLSearchParams
في بعض الحالات المعقدة، يمكنك استخدام URLSearchParams
(السطور 49-57) لبناء سلسلة الاستعلام يدويًا. هذا مفيد بشكل خاص عندما تحتاج إلى تكرار نفس المعلمة عدة مرات أو عندما تتعامل مع أسماء معلمات معقدة.
أفضل الممارسات للتعامل مع معلمات URL:
- استخدم
params
لمعلمات الاستعلام والقوالب النصية لمعلمات المسار - تحقق دائمًا من صحة المعلمات قبل استخدامها في URL
- استخدم
encodeURIComponent
عند إدراج قيم المستخدم يدويًا في عنوان URL - استخدم
paramsSerializer
للتعامل مع حالات خاصة مثل المصفوفات المتعددة - فكر في استخدام وظائف مساعدة لبناء عناوين URL المعقدة للحفاظ على نظافة الكود
رفع الملفات
يدعم Axios رفع الملفات باستخدام طلبات multipart/form-data
. سنتعرف على كيفية رفع ملف واحد أو عدة ملفات وكيفية إرسال بيانات إضافية مع الملفات.
رفع الملفات مع Axios
// 1. رفع ملف واحد
// هب رمز من جافا سكريبت في المتصفح، مع نموذج HTML
const fileInput = document.querySelector('#fileInput');
const submitButton = document.querySelector('#submitButton');
submitButton.addEventListener('click', async () => {
// التحقق من وجود ملف
if (!fileInput.files[0]) {
alert('الرجاء اختيار ملف');
return;
}
// إنشاء كائن FormData
const formData = new FormData();
// إضافة الملف
formData.append('file', fileInput.files[0]);
// إضافة بيانات إضافية
formData.append('description', 'ملف الملف الشخصي');
formData.append('userId', '123');
try {
const response = await axios.post('https://api.example.com/upload', formData, {
headers: {
'Content-Type': 'multipart/form-data' // اختياري: Axios يضبط هذا تلقائيًا
},
onUploadProgress: progressEvent => {
// حساب نسبة التقدم
const percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total);
console.log(`تم رفع ${percentCompleted}%`);
// يمكنك تحديث شريط التقدم هنا
}
});
console.log('تم رفع الملف بنجاح:', response.data);
} catch (error) {
console.error('خطأ في رفع الملف:', error);
}
});
// 2. رفع عدة ملفات
// بفرض أن هناك input ذو خاصية multiple
const multipleFileInput = document.querySelector('#multipleFileInput');
async function uploadMultipleFiles() {
const files = multipleFileInput.files;
if (!files || files.length === 0) {
alert('الرجاء اختيار ملف واحد على الأقل');
return;
}
const formData = new FormData();
// إضافة عدة ملفات
for (let i = 0; i < files.length; i++) {
formData.append('files', files[i]);
}
// إضافة بيانات إضافية
formData.append('albumId', '456');
try {
const response = await axios.post('https://api.example.com/upload/multiple', formData);
console.log('تم رفع الملفات بنجاح:', response.data);
} catch (error) {
console.error('خطأ في رفع الملفات:', error);
}
}
// 3. رفع ملفات في Node.js
// استخدام stream لرفع ملفات كبيرة
const fs = require('fs');
const axios = require('axios');
const FormData = require('form-data');
async function uploadFileFromNodejs(filePath) {
const form = new FormData();
// إضافة ملف كstream
const fileStream = fs.createReadStream(filePath);
form.append('file', fileStream);
try {
const response = await axios.post('https://api.example.com/upload', form, {
headers: {
...form.getHeaders() // استخدام الرؤوس التي ينشئها FormData
},
maxContentLength: Infinity, // للملفات الكبيرة
maxBodyLength: Infinity
});
console.log('تم رفع الملف من Node.js بنجاح:', response.data);
} catch (error) {
console.error('خطأ في رفع الملف من Node.js:', error);
}
}
شرح طرق رفع الملفات مع Axios
1. رفع ملف واحد (السطور 1-37)
هذا المثال يوضح كيفية رفع ملف واحد من المتصفح باستخدام FormData
. أهم الخطوات:
- الحصول على الملف من عنصر الإدخال (السطر 3)
- إنشاء كائن
FormData
جديد (السطر 14) - إضافة الملف إلى
FormData
باستخدامappend
(السطر 17) - إضافة بيانات إضافية إذا لزم الأمر (السطور 20-21)
- إرسال
FormData
باستخدامaxios.post
(السطور 24-33)
يمكنك أيضًا تتبع تقدم الرفع باستخدام onUploadProgress
(السطور 28-32)، وهي ميزة مفيدة لعرض شريط تقدم للمستخدم.
2. رفع عدة ملفات (السطور 39-64)
لرفع عدة ملفات في وقت واحد، يمكنك استخدام عنصر إدخال مع multiple
وإضافة كل ملف إلى FormData
بنفس الاسم. هذا يخبر الخادم أن هناك مصفوفة من الملفات. الخطوات الرئيسية:
- الحصول على قائمة الملفات (السطر 44)
- إضافة كل ملف إلى
FormData
باستخدام نفس الاسم (السطور 52-54)
3. رفع ملفات من Node.js (السطور 66-92)
لرفع الملفات من بيئة Node.js، تحتاج إلى استخدام حزمة form-data
وتدفقات الملفات. الخطوات الرئيسية:
- إنشاء تدفق قراءة للملف باستخدام
fs.createReadStream
(السطر 77) - إضافة التدفق إلى
FormData
(السطر 78) - استخدام
form.getHeaders()
للحصول على الرؤوس الصحيحة (السطر 83) - ضبط
maxContentLength
وmaxBodyLength
للملفات الكبيرة (السطور 85-86)
نصائح لرفع الملفات:
- استخدم
onUploadProgress
لعرض تقدم الرفع للمستخدم - تحقق من أقصى حجم للملف يقبله الخادم لتجنب الأخطاء
- أضف التحقق من نوع الملف وحجمه قبل البدء في الرفع
- استخدم
AbortController
للسماح للمستخدم بإلغاء عملية الرفع - قم بضغط الصور أو تقليل حجمها في الواجهة الأمامية قبل الرفع إذا أمكن
تنزيل الملفات
يمكن استخدام Axios لتنزيل الملفات وحفظها أو عرضها. سنستعرض كيفية تنزيل الملفات في المتصفح وفي بيئة Node.js.
تنزيل الملفات مع Axios
// 1. تنزيل ملف في المتصفح وحفظه
async function downloadFile(url, filename) {
try {
// ضبط نوع الاستجابة على blob
const response = await axios.get(url, {
responseType: 'blob',
onDownloadProgress: progressEvent => {
// حساب نسبة التقدم
const percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total);
console.log(`تم تنزيل ${percentCompleted}%`);
// يمكنك تحديث شريط التقدم هنا
}
});
// إنشاء URL للكائن Blob
const url = window.URL.createObjectURL(new Blob([response.data]));
// إنشاء عنصر رابط مؤقت
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', filename);
// إضافة الرابط إلى المستند والنقر عليه
document.body.appendChild(link);
link.click();
// تنظيف بعد التنزيل
window.URL.revokeObjectURL(url);
document.body.removeChild(link);
} catch (error) {
console.error('خطأ في تنزيل الملف:', error);
}
}
// استخدام الدالة
downloadFile('https://example.com/files/report.pdf', 'تقرير.pdf');
// 2. عرض صورة أو PDF في المتصفح
async function viewFile(url) {
try {
const response = await axios.get(url, {
responseType: 'blob'
});
// إنشاء URL للكائن Blob
const objectUrl = URL.createObjectURL(response.data);
// افتراضاً أن هناك عنصر img أو iframe في الصفحة
if (response.headers['content-type'].startsWith('image/')) {
// للصور
document.getElementById('imageViewer').src = objectUrl;
} else if (response.headers['content-type'] === 'application/pdf') {
// للملفات PDF
document.getElementById('pdfViewer').src = objectUrl;
}
} catch (error) {
console.error('خطأ في عرض الملف:', error);
}
}
// 3. تنزيل ملف في Node.js وحفظه
const fs = require('fs');
const path = require('path');
const axios = require('axios');
async function downloadFileInNodejs(url, outputPath) {
try {
// إنشاء تدفق كتابة
const writer = fs.createWriteStream(outputPath);
// الحصول على الاستجابة كتدفق
const response = await axios({
method: 'get',
url: url,
responseType: 'stream'
});
// أنبوب الاستجابة إلى ملف
response.data.pipe(writer);
// إنشاء وعد يكتمل عند اكتمال التنزيل
return new Promise((resolve, reject) => {
writer.on('finish', () => {
console.log(`تم تنزيل الملف وحفظه في ${outputPath}`);
resolve(outputPath);
});
writer.on('error', reject);
});
} catch (error) {
console.error('خطأ في تنزيل الملف في Node.js:', error);
throw error;
}
}
// استخدام الدالة في Node.js
downloadFileInNodejs('https://example.com/files/data.csv', 'data.csv');
شرح طرق تنزيل الملفات مع Axios
1. تنزيل ملف وحفظه في المتصفح (السطور 1-32)
هذا المثال يوضح كيفية تنزيل ملف وحفظه في المتصفح. النقاط الرئيسية:
- ضبط
responseType: 'blob'
لتلقي البيانات الثنائية (السطر 6) - استخدام
onDownloadProgress
لتتبع تقدم التنزيل (السطور 7-12) - إنشاء URL من كائن Blob لاستخدامه في التنزيل (السطر 16)
- إنشاء عنصر رابط وهمي وتنفيذ النقر عليه لبدء التنزيل (السطور 19-24)
- تنظيف الموارد بعد التنزيل بإزالة URL والعنصر المؤقت (السطور 27-28)
2. عرض ملف في المتصفح (السطور 35-54)
بدلاً من تنزيل الملف، يمكنك عرضه مباشرة في المتصفح. هذا مفيد للصور وملفات PDF وأنواع أخرى من الوسائط:
- استخدام
responseType: 'blob'
كما في المثال السابق (السطر 38) - إنشاء URL للكائن Blob لاستخدامه في عنصر العرض (السطر 42)
- تحديد نوع الملف من رأس
content-type
واستخدام العنصر المناسب لعرضه (السطور 45-50)
3. تنزيل ملف في Node.js (السطور 56-86)
في بيئة Node.js، نستخدم نهجًا مختلفًا يعتمد على التدفقات (streams) لتحسين الأداء وإدارة الذاكرة:
- إنشاء تدفق كتابة باستخدام
fs.createWriteStream
(السطر 63) - ضبط
responseType: 'stream'
للحصول على البيانات كتدفق (السطر 68) - توجيه تدفق الاستجابة إلى تدفق الكتابة باستخدام
pipe
(السطر 71) - إنشاء وعد يتم حله عند اكتمال الكتابة أو رفضه عند حدوث خطأ (السطور 74-80)
أفضل الممارسات لتنزيل الملفات:
- استخدم
responseType
المناسب: 'blob' للمتصفح و'stream' لـ Node.js - قم بتنفيذ تتبع التقدم باستخدام
onDownloadProgress
لتحسين تجربة المستخدم - تعامل مع أخطاء الشبكة وتقطع الاتصال
- في Node.js، استخدم التدفقات بدلاً من تحميل الملف بأكمله في الذاكرة
- تحقق من أذونات الكتابة في Node.js قبل محاولة حفظ الملف
تحويل البيانات
يتيح Axios تحويل البيانات قبل إرسالها أو بعد استلامها باستخدام transformRequest
و transformResponse
. هذه الميزة مفيدة لمعالجة البيانات بشكل موحد عبر التطبيق.
تحويل البيانات في Axios
// إعداد تحويلات البيانات
const axios = require('axios');
// إنشاء نسخة مخصصة من Axios مع تحويلات
const api = axios.create({
baseURL: 'https://api.example.com',
// تحويل البيانات قبل إرسال الطلب
transformRequest: [
// الدالة الافتراضية من Axios (تحويل الكائنات إلى JSON)
...axios.defaults.transformRequest,
// تحويل مخصص إضافي
function(data, headers) {
// مثال: تحويل التواريخ إلى صيغة ISO
if (data && typeof data === 'object') {
Object.keys(data).forEach(key => {
if (data[key] instanceof Date) {
data[key] = data[key].toISOString();
}
});
}
// إضافة توقيع أو طابع زمني
if (data && typeof data === 'string') {
const timestamp = new Date().getTime();
data = `${data}×tamp=${timestamp}`;
}
return data;
}
],
// تحويل البيانات بعد استلام الاستجابة
transformResponse: [
// الدالة الافتراضية من Axios (تحليل JSON)
...axios.defaults.transformResponse,
// تحويل مخصص إضافي
function(data) {
// مثال: تحويل سلاسل التواريخ إلى كائنات Date
if (data && typeof data === 'object') {
// نمط لسلسلة ISO date
const isoDatePattern = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z$/;
// دالة مساعدة لتحويل السلاسل النصية إلى كائنات Date
const convertDates = (obj) => {
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
if (typeof obj[key] === 'string' && isoDatePattern.test(obj[key])) {
obj[key] = new Date(obj[key]);
} else if (typeof obj[key] === 'object' && obj[key] !== null) {
convertDates(obj[key]);
}
}
}
};
convertDates(data);
}
// مثال: تطبيع البيانات
if (data && data.items) {
data.normalizedItems = data.items.reduce((acc, item) => {
acc[item.id] = item;
return acc;
}, {});
}
return data;
}
]
});
// استخدام النسخة المخصصة
async function fetchUserData() {
try {
const response = await api.get('/users');
// البيانات مع التواريخ التي تم تحويلها بالفعل
console.log(response.data);
// استخدام البيانات المطبعة
if (response.data.normalizedItems) {
const user = response.data.normalizedItems['123'];
console.log('تاريخ الإنشاء:', user.createdAt.toLocaleDateString());
}
} catch (error) {
console.error('خطأ:', error);
}
}
شرح تحويلات البيانات في Axios
1. transformRequest
هذا التحويل يحدث قبل إرسال البيانات إلى الخادم (السطور 8-29). يمكنك استخدامه لما يلي:
- تحويل كائنات Date إلى سلاسل نصية متوافقة مع الخادم (السطور 15-21)
- إضافة طوابع زمنية أو توقيعات (السطور 23-27)
- تنسيق البيانات وفقًا لمتطلبات API
- ضغط أو تشفير البيانات
ملاحظة: يتم دمج تحويلات Axios الافتراضية (مثل تحويل الكائنات إلى JSON) مع التحويلات المخصصة باستخدام ...axios.defaults.transformRequest
(السطر 11).
2. transformResponse
هذا التحويل يحدث بعد استلام البيانات من الخادم (السطور 32-65). يمكنك استخدامه لما يلي:
- تحويل سلاسل التواريخ إلى كائنات Date (السطور 40-54)
- تطبيع البيانات للاستخدام السهل في التطبيق (السطور 57-62)
- تنظيف البيانات أو تصفيتها
- إضافة حسابات أو خصائص مشتقة
مثل transformRequest
، يتم دمج التحويلات الافتراضية (مثل تحليل JSON) مع التحويلات المخصصة (السطر 35).
مزايا استخدام تحويلات البيانات:
- تطبيق منطق تحويل البيانات بشكل موحد عبر جميع الطلبات
- فصل منطق معالجة البيانات عن منطق الأعمال الرئيسي
- تجنب تكرار الكود للعمليات الشائعة مثل تحويل التواريخ
- تسهيل اختبار تحويلات البيانات بشكل منفصل
- تبسيط الكود في مكونات التطبيق حيث تستخدم البيانات
إعدادات HTTPS
عند العمل مع اتصالات HTTPS، قد تحتاج إلى تخصيص سلوك وكيل HTTPS في Axios، خاصةً عند التعامل مع شهادات موقعة ذاتيًا أو متطلبات أمان مخصصة.
تكوين وكيل HTTPS
// هذه الأمثلة خاصة بـ Node.js فقط
const axios = require('axios');
const https = require('https');
const fs = require('fs');
// 1. تجاهل أخطاء الشهادة (لا ينصح به في الإنتاج)
const insecureAgent = new https.Agent({
rejectUnauthorized: false
});
axios.get('https://self-signed.example.com', {
httpsAgent: insecureAgent
})
.then(response => console.log('تم الاتصال بالخادم'))
.catch(error => console.error('خطأ:', error));
// 2. استخدام شهادات مخصصة
const customAgent = new https.Agent({
// قراءة الشهادة والمفتاح من الملفات
cert: fs.readFileSync('./client-cert.pem'),
key: fs.readFileSync('./client-key.pem'),
// شهادة CA المخصصة للتحقق من شهادة الخادم
ca: fs.readFileSync('./ca-cert.pem')
});
axios.get('https://secure-api.example.com', {
httpsAgent: customAgent
})
.then(response => console.log('تم الاتصال بالخادم'))
.catch(error => console.error('خطأ:', error));
// 3. تكوين وكيل HTTPS لنسخة محددة من Axios
const secureApi = axios.create({
baseURL: 'https://secure-api.example.com',
httpsAgent: new https.Agent({
cert: fs.readFileSync('./client-cert.pem'),
key: fs.readFileSync('./client-key.pem'),
ca: fs.readFileSync('./ca-cert.pem'),
// خيارات إضافية
minVersion: 'TLSv1.2', // الحد الأدنى من إصدار TLS
maxVersion: 'TLSv1.3', // الحد الأقصى من إصدار TLS
ciphers: 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256', // تحديد خوارزميات التشفير
})
});
// 4. إعداد وكيل HTTPS مع إعادة المحاولات والمهلة
const advancedAgent = new https.Agent({
keepAlive: true, // الاحتفاظ بالاتصالات نشطة لتحسين الأداء
maxSockets: 25, // الحد الأقصى للاتصالات المتزامنة لكل مضيف
maxFreeSockets: 10, // الحد الأقصى للاتصالات غير المستخدمة في مجموعة الاتصال
timeout: 10000, // مهلة بالميللي ثانية
cert: fs.readFileSync('./client-cert.pem'),
key: fs.readFileSync('./client-key.pem')
});
const apiWithRetry = axios.create({
baseURL: 'https://api.example.com',
httpsAgent: advancedAgent,
timeout: 30000, // مهلة كلية للطلب
// إعادة محاولة الطلب عند الفشل (باستخدام مكتبة خارجية مثل axios-retry)
'axios-retry': {
retries: 3,
retryDelay: retryCount => retryCount * 1000,
retryCondition: error => {
return !error.response || error.response.status >= 500;
}
}
});
شرح خيارات وكيل HTTPS
1. تجاهل أخطاء الشهادة (السطور 6-14)
باستخدام rejectUnauthorized: false
، يمكنك تجاهل أخطاء التحقق من صحة شهادة SSL/TLS. هذا مفيد للتطوير والاختبار، لكنه غير آمن للاستخدام في بيئة الإنتاج.
2. استخدام شهادات مخصصة (السطور 16-28)
عند الاتصال بخوادم تتطلب مصادقة متبادلة (mutual TLS)، يمكنك تكوين وكيل HTTPS باستخدام شهادات ومفاتيح العميل. يمكنك أيضًا تحديد شهادة CA مخصصة للتحقق من شهادة الخادم.
3. تكوين نسخة محددة من Axios (السطور 30-43)
يمكنك إنشاء نسخة مخصصة من Axios مع إعدادات HTTPS محددة. هذا مفيد عند التعامل مع عدة خدمات تتطلب إعدادات أمان مختلفة. يمكنك أيضًا تحديد إصدارات TLS وخوارزميات التشفير المدعومة.
4. إعداد متقدم مع إعادة المحاولات (السطور 45-65)
يمكنك تحسين أداء وثبات اتصالات HTTPS باستخدام خيارات متقدمة مثل:
keepAlive
: الاحتفاظ بالاتصالات نشطة لتقليل تأخير إنشاء اتصال جديدmaxSockets
: التحكم في عدد الاتصالات المتزامنةtimeout
: تحديد مهلة على مستوى وكيل HTTPS- إضافة منطق إعادة المحاولة للتعامل مع الأخطاء المؤقتة
ملاحظات هامة:
- الإعدادات المذكورة أعلاه خاصة بـ Node.js فقط ولا تنطبق على المتصفح
- في المتصفح، يتم التعامل مع إعدادات HTTPS من قبل المتصفح نفسه
- تجنب تعطيل التحقق من الشهادات (
rejectUnauthorized: false
) في بيئة الإنتاج - احتفظ بالشهادات والمفاتيح في مكان آمن وليس مباشرة في الكود
- استخدم متغيرات البيئة أو خدمات تخزين الأسرار لإدارة بيانات الاعتماد
الخلاصة
تعرفنا في هذا التوثيق على مكتبة Axios وكيفية استخدامها لإرسال طلبات HTTP بسهولة وفعالية. من الإعدادات الأساسية إلى الميزات المتقدمة، Axios توفر واجهة برمجية قوية وسهلة الاستخدام للتعامل مع واجهات برمجة التطبيقات وخدمات الويب.
استمر في استكشاف الأمثلة والتطبيقات العملية، وتذكر دائمًا الرجوع إلى هذا التوثيق والمصادر الرسمية لمكتبة Axios لمزيد من المعلومات التفصيلية.