AzLearn

Promises

Promises

مفهوم ~18 دقيقة

Promises

Promise<T> تعني قيمة ستتوفر لاحقاً من نوع T. طلب API لا يعطيك النتيجة فوراً، بل وعداً. TypeScript يجعل هذا الوعد typed. إذا كانت الدالة ترجع Promise<User>, فعند await تحصل على User.

لا تخلط بين User وPromise<User>. الأول بيانات موجودة الآن، والثاني عملية لم تنته بعد. هذا التمييز مهم لأنه يمنع استخدام البيانات قبل وصولها.

مثال عملي

index.ts

داخل then, يعرف TypeScript أن user من نوع User.

تحذير: Promise العائم — Floating Promise

loadUser() بدون await أو .then هو خطأ صامت يُسمى “floating promise”. الكود يعمل بدون انتظار النتيجة، والأخطاء تختفي بلا أثر:

// خطأ — The promise is not handled
loadUser();

// صواب — أضف await أو .then
await loadUser();
loadUser().then(handleResult).catch(handleError);

يكتشف ESLint هذا بقاعدة @typescript-eslint/no-floating-promises. فعّلها في مشاريع production.

try/catch الصحيح مع await

// صواب — try/catch يلتقط أخطاء await
async function run(): Promise<void> {
  try {
    const user = await loadUser();
    console.log(user.name);
  } catch (err) {
    console.error("فشل التحميل", err);
  }
}

// خطأ — try/catch لا يلتقط أخطاء .then بعده
try {
  loadUser().then((u) => {
    // إذا رمت هنا، لن يلتقطها catch الخارجي
    throw new Error("oops");
  });
} catch (err) {
  // لن يصل هنا
}

Promise.all يتوقف عند أول رفض

Promise.all([p1, p2, p3]) ينتظر الجميع. إذا فشل واحد، فشل الكل:

index.ts

إذا رفضت إحدى الوعود، لن تستقبل نتائج الأخريات حتى لو نجحت. استخدم Promise.allSettled إذا أردت النتائج الجزئية.

الأخطاء

Promise قد تفشل. لا تصمم كل شيء كأنه ينجح. لاحقاً سنستخدم Result types لتمثيل النجاح والفشل بشكل أوضح.

تحدي — Challenge