مقدمة إلى JavaScript غير المتزامن و Fetch API


مقدمة إلى البرمجة غير المتزامنة

في عالم تطوير الويب، غالبًا ما نحتاج إلى تنفيذ عمليات تستغرق وقتًا طويلاً ولا يمكننا إيقاف تنفيذ بقية البرنامج في انتظارها. على سبيل المثال، عند جلب بيانات من خادم بعيد عبر الشبكة. هنا يأتي دور البرمجة غير المتزامنة (Asynchronous Programming).

تسمح لنا البرمجة غير المتزامنة ببدء مهمة قد تستغرق وقتًا، ثم الاستمرار في تنفيذ مهام أخرى دون انتظار المهمة الأولى حتى تنتهي. عندما تكتمل المهمة الطويلة، يتم إعلام برنامجنا ويمكنه معالجة النتيجة.

Async/Await: تبسيط التعامل مع الوعود (Promises)

قبل ظهور async/await، كانت الوعود (Promises) هي الطريقة الأساسية للتعامل مع العمليات غير المتزامنة في JavaScript. على الرغم من قوتها، إلا أن سلاسل الوعود المتعددة (Promise Chaining) يمكن أن تصبح معقدة وصعبة القراءة (ما يُعرف بـ "Callback Hell" أو "Promise Hell").

جاءت الكلمتان المفتاحيتان async و await لتبسيط كتابة الكود غير المتزامن وجعله يبدو وكأنه كود متزامن (Sequential Code)، مما يحسن من قابلية القراءة والصيانة.

  • async: تُستخدم قبل تعريف الدالة (function) لتحديد أنها دالة غير متزامنة. الدالة async دائمًا ما تُرجع وعدًا (Promise).
  • await: تُستخدم داخل دالة async فقط. توقف تنفيذ الدالة async مؤقتًا حتى يكتمل الوعد الذي يليه await ويتم تسوية قيمته (fulfilled) أو رفضه (rejected). القيمة المسواة هي القيمة التي يتم إرجاعها بواسطة التعبير await.

async function myFunction() {
  // ... كود غير متزامن ...
  const result = await somePromiseFunction();
  // ... تابع استخدام result ...
}
    

Fetch API: جلب البيانات من الشبكة

تُعد Fetch API واجهة برمجية حديثة وقوية في المتصفحات (ومتوفرة في Node.js عبر مكتبات إضافية) لجلب الموارد عبر الشبكة. إنها بديل أكثر مرونة وقوة لـ XMLHttpRequest القديم.

تُرجع الدالة fetch() وعدًا (Promise) يتم تسويته بكائن Response عندما يتم استلام رأس (Headers) الاستجابة بنجاح، حتى لو كانت الاستجابة HTTP 404 أو 500. لرفض الوعد، يجب أن تكون هناك مشكلة في الشبكة نفسها (مثل عدم الاتصال بالإنترنت).

التعامل مع كائن الاستجابة (Response Object)

  • response.ok: خاصية منطقية (Boolean) تُرجع true إذا كانت حالة الاستجابة ضمن النطاق 200-299 (مما يشير إلى نجاح الطلب).
  • response.json(): أسلوب يُستخدم لتحويل نص جسم الاستجابة إلى كائن JavaScript JSON. هذا الأسلوب نفسه يُرجع وعدًا آخر، لذا غالبًا ما نستخدم await معه أيضًا.
  • response.text(): لتحويل جسم الاستجابة إلى نص عادي.

معالجة الأخطاء باستخدام Try...Catch

عند التعامل مع العمليات غير المتزامنة، من الضروري معالجة الأخطاء المحتملة. توفر try...catch آلية قوية للقيام بذلك في JavaScript، وتعمل بشكل ممتاز مع async/await.

  • try بلوك: يحتوي على الكود الذي قد يرمي خطأً.
  • catch بلوك: يتم تنفيذه إذا تم رمي خطأ داخل بلوك try. يستقبل كائن الخطأ كمعامل.

أي خطأ يتم رميه (سواء كان خطأ شبكة، أو خطأ في تحليل JSON، أو خطأ تم رميه يدويًا باستخدام throw new Error()) داخل دالة async يمكن التقاطه بواسطة بلوك catch المحيط.


async function fetchDataWithErrorHandling() {
  try {
    const response = await fetch('invalid-url'); // هذا سيسبب خطأ
    if (!response.ok) {
      throw new Error('فشل جلب البيانات');
    }
    const data = await response.json();
    console.log(data);
  } catch (error) {
    console.error('حدث خطأ:', error.message);
  }
}
fetchDataWithErrorHandling();
    


🔗 الخطوة التالية: انتقل إلى التطبيق العملي وجرب الكود بنفسك من هنا.