async وawait: تصميم تدفق أخطاء يمكن الوثوق به

تعلم كتابة عمليات غير متزامنة واضحة، وتشغيل الطلبات المستقلة بالتوازي، وتصنيف الأخطاء بدل ابتلاعها برسالة عامة.

أسامة زيدانآخر تحديث: ١٨ يوليو ٢٠٢٦13 دقيقة قراءة

await ليست بديلًا عن تصميم التدفق

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

كل دالة async تعيد Promise. إذا أرجعت قيمة عادية تتحول إلى Promise ناجحة، وإذا رميت خطأ تتحول إلى Promise مرفوضة. لذلك على المستدعي إما استخدام await داخل try/catch أو إرجاع الوعد إلى طبقة تعرف كيف تعالجه.

لا تخلط أنواع الأخطاء

fetch لا يرمي خطأ لمجرد أن الخادم أعاد 404 أو 500؛ يرمي عادةً عند فشل الشبكة أو إلغاء الطلب. يجب فحص response.ok ثم قراءة جسم الاستجابة بطريقة آمنة. بعد ذلك قد يفشل تحليل JSON أو قد تكون البنية صحيحة نحويًا لكنها لا تطابق ما يتوقعه التطبيق.

صنّف الأخطاء إلى فئات يمكن للواجهة فهمها: انقطاع اتصال، رفض صلاحية، بيانات غير صحيحة، أو عطل خادم مؤقت. لا تعرض stack trace للمستخدم، ولا تحوّل كل شيء إلى «حدث خطأ» لأن ذلك يمنع قرار إعادة المحاولة أو طلب تسجيل الدخول.

طبقة صغيرة تفصل فشل HTTP عن فشل الشبكة.
class HttpError extends Error {
  constructor(public status: number, message: string) {
    super(message);
  }
}

async function getGuide(slug: string) {
  const response = await fetch(`/api/guides/${slug}`);

  if (!response.ok) {
    throw new HttpError(response.status, "تعذر تحميل الدليل");
  }

  return response.json();
}

التوازي المقصود والإلغاء

إذا احتاجت الصفحة إلى الملف الشخصي وقائمة الأدلة ولا تعتمد إحداهما على الأخرى، ابدأ الوعدين ثم انتظرهما بواسطة Promise.all. إذا فشلت عملية واحدة تفشل المجموعة، وهو مناسب عندما لا يمكن عرض الصفحة دون كل النتائج. استخدم Promise.allSettled عندما تستطيع عرض نتيجة جزئية وتوضيح ما فشل.

استخدم AbortController لإلغاء طلب لم يعد مطلوبًا، مثل بحث تغيّر نصه أو صفحة غادرها المستخدم. الإلغاء ليس خطأ يحتاج رسالة حمراء دائمًا؛ غالبًا هو نهاية متوقعة لعمل أصبح قديمًا.

  • لا تعِد المحاولة تلقائيًا لطلب دفع أو عملية غير قابلة للتكرار دون مفتاح idempotency.
  • ضع مهلة واضحة للطلبات التي قد تعلق.
  • سجل تفاصيل تقنية آمنة على الخادم واعرض رسالة قابلة للتنفيذ للمستخدم.

قاعدة مراجعة قبل الدمج

راجع كل await واسأل: هل العملية مستقلة عن السطر السابق؟ من يملك معالجة الخطأ؟ هل يمكن إلغاء العمل؟ وهل إعادة المحاولة آمنة؟ هذه الأسئلة تكشف غالبية مشكلات الأداء والموثوقية قبل الاختبار.

اكتب اختبارًا للمسار الناجح، واستجابة 4xx، واستجابة 5xx، وفشل الشبكة، والإلغاء. عندما تكون نتيجة كل حالة محددة، تصبح الشيفرة غير المتزامنة مملة وقابلة للتوقع، وهذه ميزة وليست عيبًا.

المراجع ومزيد من القراءة

عن المؤلف

يراجع أسامة زيدان محتوى كود هاب بهدف تقديم شرح عربي واضح يربط المفاهيم البرمجية بالقرارات التي يواجهها المتعلم أثناء التطبيق.

صفحة المؤلف