حول المحتوى:
في هذا المقال، سنتعرّف على كيفية إعادة الاستجابة من نداء غير متزامن في JavaScript، مع شرح مبسّط للأدوات الأساسية مثل Promises، و async/await، وبعض الأخطاء الشائعة التي يقع فيها المبرمجون أثناء التعامل مع هذا النمط.
في JavaScript، تعد العمليات غير المتزامنة جزءًا أساسيًا من التعامل مع المهام التي تستغرق وقتًا في التنفيذ، مثل طلب بيانات من خادم خارجي أو التعامل مع الملفات أو مؤقتات الانتظار. العمليات غير المتزامنة تختلف عن العمليات العادية المتتابعة في أن المتصفح لا يتوقف في انتظار نتيجتها، بل يستمر في تنفيذ باقي التعليمات، وعند انتهاء العملية يتم تنفيذ كود معين لاستلام النتيجة. وهنا يظهر السؤال: كيف يمكن إعادة النتيجة من نداء غير متزامن بطريقة صحيحة؟
لتحقيق ذلك، وفّرت JavaScript طريقتين أساسيتين: إما باستخدام Promise مع then أو من خلال async/await. وفيما يلي توضيح عملي لطريقتي التنفيذ.
هو ببساطة عملية تنفّذ في الخلفية ولا ينتظرها البرنامج حتى تنتهي قبل أن يُكمل تنفيذ الأوامر التالية. مثال ذلك: عند إرسال طلب بيانات باستخدام fetch
، لن ينتظر المتصفح وصول الرد ليكمل باقي الكود، بل سيواصل التنفيذ ويُكمل الطلب في الخلفية.
عند استدعاء عملية غير متزامنة مثل fetch
، فإنها تُعيد كائن من نوع Promise. هذا الكائن يحتوي على نتيجة العملية بمجرد اكتمالها. ويمكن استخدام then لاستلام هذه النتيجة.
function getData() {
return fetch('https://api.example.com/data')
.then(response => response.json())
.then(data => {
console.log(data);
return data;
});
}
getData().then(result => {
console.log('Received data:', result);
});
في هذا المثال:
تقوم دالة getData
بطلب بيانات من عنوان معين.
تستخدم then لمعالجة الاستجابة وتحويلها إلى JSON.
يتم إرجاع البيانات.
عند استدعاء getData()
يتم التعامل مع النتيجة النهائية باستخدام then.
لا يمكن إعادة النتيجة مباشرة من داخل then إلى خارج الدالة المتزامنة، لذا يجب إرجاع Promise نفسه والتعامل مع نتيجته عند استدعاء الدالة.
تعتبر طريقة async/await أكثر وضوحًا وحداثة في كتابة الكود. إذ تتيح انتظار نتيجة العملية غير المتزامنة بطريقة تشبه الكود المتزامن العادي، مما يجعل القراءة والفهم أسهل.
async function getData() {
const response = await fetch('https://api.example.com/data');
const data = await response.json();
return data;
}
getData().then(result => {
console.log('Received data:', result);
});
في هذا المثال:
تم تحويل دالة getData
إلى دالة غير متزامنة باستخدام async.
باستخدام await تم الانتظار لحين انتهاء تنفيذ fetch.
بعد الحصول على الاستجابة تم تحويلها إلى JSON.
تم إرجاع البيانات.
عند استدعاء الدالة، يتم التعامل مع Promise الناتجة عن الدالة باستخدام then.
كود أكثر وضوحًا وسهولة في القراءة.
تسلسل منطقي يشبه الكود المتزامن.
إمكانية التعامل مع الأخطاء بسهولة من خلال try-catch.
async function getData() {
try {
const response = await fetch('https://api.example.com/data');
const data = await response.json();
return data;
} catch (error) {
console.error('Error fetching data:', error);
}
}
كثير من المبتدئين يقعون في خطأ محاولة استرجاع القيمة من Promise بشكل مباشر داخل دالة متزامنة، معتقدين أن القيمة ستكون متوفرة لحظة إرجاعها.
function getData() {
let result;
fetch('https://api.example.com/data')
.then(response => response.json())
.then(data => result = data);
return result; // ستعود undefined
}
console.log(getData());
في هذا المثال، عند تنفيذ getData()
سيتم تنفيذ fetch في الخلفية، بينما الدالة سترجع undefined مباشرة قبل اكتمال عملية جلب البيانات.
يجب إرجاع Promise نفسه:
function getData() {
return fetch('https://api.example.com/data')
.then(response => response.json());
}
getData().then(data => console.log(data));
أو باستخدام async/await:
async function getData() {
const response = await fetch('https://api.example.com/data');
const data = await response.json();
return data;
}
getData().then(data => console.log(data));
إذا كان الكود بسيطًا ولا يتضمن العديد من العمليات المتداخلة، يمكن استخدام then.
إذا كان الكود يحتوي على عدة عمليات غير متزامنة متتابعة، من الأفضل استخدام async/await لأنه أكثر وضوحًا وأسهل في القراءة.
الدوال التي تحتوي على await يجب أن يُصرح بها باستخدام async.
دوال async دائمًا تعيد Promise.
يمكن استخدام await فقط داخل دوال async.
بهذا الشكل يصبح التعامل مع العمليات غير المتزامنة في JavaScript واضحًا وسهل التطبيق باستخدام طريقتين أساسيتين، مع ضرورة تجنب الخطأ الشائع المتعلق بمحاولة استرجاع قيمة من Promise داخل دالة متزامنة.
في هذا المقال، سنتعرّف على كيفية إعادة الاستجابة من نداء غير متزامن في JavaScript، مع شرح مبسّط للأدوات الأساسية مثل Promises، و async/await، وبعض الأخطاء الشائعة التي يقع فيها المبرمجون أثناء التعامل مع هذا النمط.
مساحة اعلانية
HTTP هو بروتوكول يستخدم لنقل البيانات بين المتصفحات والخوادم.