تخطَّ إلى المحتوى

الـ Async

الدرس 12 من 20

الهدف

بنهاية الدرس تفهم ليش JavaScript single-threaded وكيف async/await يحل المشكلة، تكتب async function بـ try/catch صحيح، وتشغّل عمليتين بالتوازي بـ Promise.all.

ليش هذا الحين؟

ترى كل شي مهم في الـ app هو async — قراءة بيانات من قاعدة البيانات، جلب ملف، إرسال email، استدعاء external API. لو ما تفهم async، ما تقدر تكتب app حقيقي. والمشكلة إن الـ async/await شكلها بسيطة بس وايد من الناس يستخدمونها غلط — ينسون await، ما يعالجون الأخطاء، أو يشغّلون عمليات بالتسلسل وهي تقدر تشتغل بالتوازي. هالدرس يصلح كل هذا.

الفكرة

JavaScript = single-threaded. يعني هو يشتغل على خيط واحد بس — تعليمة واحدة في كل مرة. لو شغّلت عملية تاخذ وقت (مثلا database query) بدون async، الـ thread ينتظر ويتجمد — الـ UI ما يستجيب لأي click أو حركة.

الحل: Non-blocking async.

JavaScript يبدأ العملية ويروح يكمل شغل ثاني. لما العملية تخلص، يرجع يكمل.

Blocking (سيء):
[DB Query] → انتظار... → انتظار... → [تم] → [كود يتابع]
(الـ UI مجمّد طول هذي الفترة)

Non-blocking (صح):
[ابدأ DB Query] → [كود يكمل يشتغل] → [DB رجع] → [تابع]
(الـ UI شغّال طول الوقت)

التطور التاريخي:

الـ Callbacks جت أولا — وسبّبت "callback hell":

// callback hell — قبيح وصعب تتبعه
getUser(id, (user) => {
  getPosts(user.id, (posts) => {
    getComments(posts[0].id, (comments) => {
      // ثلاث طبقات — والموضوع يزيد
    })
  })
})

بعدين Promises:

// أحسن بس لسه verbose
getUser(id)
  .then(user => getPosts(user.id))
  .then(posts => getComments(posts[0].id))
  .catch(err => console.error(err))

الحين async/await — تكتب async كأنه sync:

// واضح ونظيف
async function loadData() {
  try {
    const user = await getUser(id)
    const posts = await getPosts(user.id)
    const comments = await getComments(posts[0].id)
  } catch (err) {
    console.error(err)
  }
}

القاعدة: كل await لازم يكون داخل async function. وكل async function ترجع Promise تلقائيا.

محتاج مساعدة؟ راسلنا على mj@shakesbeard.net