JavaScript / متوسط: الوحدات والعقود غير المتزامنة / الدرس 8
الوعود وتركيب العمل غير المتزامن
نمذج نتيجة مستقبلية دون خلطها بخيط عامل. تتبع حالات الوعد والسلاسل والرفض والنتائج المجمعة بعمليات محلية حتمية.
في هذه الصفحة
أهداف الدرس
- تتبع الوفاء والرفض عبر السلسلة.
- إرجاع الوعود لربط العمل.
- اختيار التجميع حسب سياسة النتيجة والإخفاق.
يمثل الوعد نتيجة لا خيطاً
يبدأ الوعد معلقاً ويستقر مرة وفاءً أو رفضاً. لا يعني الاستقرار تنفيذ العمل في خيط منفصل. يعمل منفذ المنشئ متزامناً، وتجدول معالجات then على نحو غير متزامن. قد يُحل الوعد بقيمة عادية أو يتبنى نتيجة وعد آخر؛ فالحل لا يعني الوفاء بالضرورة. فكر بالاعتماد: ما الذي يبدأ الآن، وما النتيجة التالية، ومن يلاحظ الإخفاق؟ يفيد ذلك أكثر من تسمية كل وعد عملاً خلفياً. تقرر البيئة نشاط الإدخال والإخراج الفعلي.
إرجاع الاعتماد التالي
تعيد then وعداً جديداً. يفي إرجاع قيمة بالوعد التالي، ويرفضه الرمي، ويربطه إرجاع وعد بنتيجته. قد يؤدي نسيان return إلى عمل منفصل وundefined لاحقاً. يحول المثال سعراً معروفاً ثم يرمي خطأ مجال عمداً، ويحوّله معالج الرفض إلى عرض صريح. catch تحويل أيضاً؛ فإذا عاد طبيعياً صار ما بعده ناجحاً، لذلك يجب أن تكون الاستعادة مقصودة لا إخفاءً صامتاً.
const result = await Promise.resolve(200)
.then(cents => cents + 50)
.then(cents => { throw new Error("price unavailable"); })
.catch(error => "notice: " + error.message);
console.log(result);
notice: price unavailable
يتحول Error المرمى إلى رفض الوعد التالي. تعيد catch رسالة فتكون النتيجة النهائية نصاً.
يشفر التركيب سياسة الإخفاق
تنتظر Promise.all الوفاء للجميع وتحفظ ترتيب المدخلات، لكنها ترفض عند رفض أحدها ولا تلغي البقية. تنتظر allSettled كل نتيجة وتصف وفاءها أو رفضها، فتفيد لعرض نتائج مستقلة جزئية. تتبع race أول استقرار، وتسعى any لأول وفاء وترفض إن رفض الجميع. اختر من عقد التطبيق لا أقصر صياغة؛ فشراء يحتاج التصريح والمخزون يختلف عن لوحة بطاقات معلومات مستقلة.
قراءة كل نتيجة بدلاً من تخمين النجاح
قد ينجح عنوان دورة ويفشل شارة اختيارية. تسمح allSettled بعرض العنوان وحالة شارة غير متاحة. لا تستبدل فشل عملية مطلوبة بقيمة فارغة ناجحة؛ فقد يظن المستدعي أنها بيانات فارغة مشروعة. يحول المثال النتائج إلى قائمة تشخيصية صغيرة دون مكدس خطأ كامل. وحتى لو كانت المدخلات وعوداً موفاة، تبقى معالجاتها مجدولة ولا يصير الاستدعاء الراجع متزامناً.
const outcomes = await Promise.allSettled([
Promise.resolve("DOM"),
Promise.reject(new Error("badge offline"))
]);
console.log(outcomes.map(x => x.status).join(","));
console.log(outcomes[0].value);
console.log(outcomes[1].reason.message);
fulfilled,rejected
DOM
badge offline
يحفظ ترتيب المدخل، ويبقى الفشل مختلفاً عن شارة غائبة صالحة. يربط المجمع مراقبي الرفض.
يحتاج كل عمل بدأ إلى مالك
ينبغي عادة أن تعيد الدالة التي تبدأ عملاً وعده لينتظر المستدعي ويعالج الرفض ويقرر التنظيف. يحتاج العمل المنفصل المقصود مراقب خطأ وسياسة عمر؛ فلا تعالج كتابة void الرفض سحرياً. تجنب تغليف واجهة تعيد وعداً في Promise جديد؛ فقد يفقد الغلاف الأخطاء ويخفي الإلغاء الذي يخص العملية الداعمة لا Promise ذاته. احفظ سياق السبب عند إضافة معلومات وأبعد البيانات الحساسة عن رسائل المستخدم.
الأخطاء الشائعة وإصلاحها
تلقي السلسلة undefined فجأة
- لماذا يحدث؟
- بدء العمل دون إرجاع الوعد أو القيمة.
- كيف تصلحه؟
- إرجاع نتيجة المرحلة التالية.
- كيف تتجنب تكراره؟
- اختبار القيمة ومسار خطأ السلسلة كاملة.
تحويل catch الفشل إلى نجاح صامت
- لماذا يحدث؟
- تسجيل المعالج وعودته دون عقد استعادة.
- كيف تصلحه؟
- إرجاع بديل مقصود أو إعادة رمي خطأ مفيد.
- كيف تتجنب تكراره؟
- توثيق هل تعالج catch أم تمرر.
توقع إلغاء all للطلبات الأخرى
- لماذا يحدث؟
- الخلط بين تمرير الرفض وإلغاء العملية.
- كيف تصلحه؟
- استخدام إلغاء مدعوم ومعالجة النتائج اللاحقة.
- كيف تتجنب تكراره؟
- توضيح سياسة الإلغاء عند واجهة البيئة.
اختبر فهمك
1. قد تفشل لوحتان اختياريتان مستقلاً. أي تجميع يناسب؟
اعرض الحل المشروح
استخدم allSettled لفحص النتيجتين وعرض النجاح أو عدم التوفر مستقلاً. احفظ الأسباب داخلياً وقدم رسائل آمنة. إن كانت لوحة مطلوبة للمهمة فالقبول الجزئي قرار منتج لا نتيجة آلية.
2. تستدعي then الدالة save() دون إرجاعها. ما الخطر؟
اعرض الحل المشروح
قد تتابع المرحلة التالية بـundefined قبل اكتمال الحفظ ويفلت رفضه. أعد save() لربط الاكتمال والفشل. اختبر حفظاً مرفوضاً مضبوطاً ليتأكد رصد الخطأ قبل التأكيد.
أهم ما تعلمته
- تركب الوعود الاعتمادات والنتائج ولا تنشئ خيوطاً.
- لا يصبح الرفض المعالج استعادة إلا بعقد صريح.