Dart / العقود: الأنماط والواجهات العامة والنتائج غير المتزامنة / الدرس 11
امتلاك نتائج Future وأخطائها ودلالات الانتظار
استخدم async وawait بتسلسل مقصود وملاحظة مبكرة للأخطاء وتوقعات صادقة للمهلة والإلغاء.
في هذه الصفحة
أهداف الدرس
- ميّز النتيجة المستقبلية من الخيط والعازل والعملية التي تقبل الإلغاء تلقائيا.
- ضع معالجة الخطأ عند العملية المنتظرة، واحفظ ملكية الإتمام أو التنظيف.
يظل للعمل غير المتزامن نموذج تنفيذ
تمثل Future قيمة أو خطأ سيكتمل لاحقا. تتيح async إرجاع Future وانتظار النتائج عبر await، لكنها لا تنقل الحساب لعازل آخر ولا تجعل أي شيفرة متوازية. تشترك أعمال العازل الواحد في تنفيذ حلقة أحداثه؛ فقد يؤخر حساب متزامن طويل الأحداث حتى داخل دالة async. يسمح انتظار الإدخال والإخراج بمعالجة عمل آخر أثناء التعليق. افصل الآليات قبل ادعاء الاستجابة؛ فالانتظار غير المتزامن وتوازي الحساب والمعالجة الخلفية الدائمة اختيارات معمارية مختلفة.
ابدأ العمليات المرتبطة وراقبها عمدا
يفرض انتظار عملية ثم بدء الأخرى تسلسلا. وقد يتيح بدء عمليات مستقلة أولا ثم انتظار مجموع نتائجها تداخلا إذا نفذت عملا غير متزامن فعلا. تربط Future.wait النتائج بترتيب المدخل لا الإتمام. يستخدم المثال حسابات ثابتة بسيطة لشرح ملكية النتائج لا تحسين السرعة. أرفق معالجة الأخطاء مبكرا؛ فقد يظهر خطأ Future تُترك دون مراقبة أثناء انتظار عمل آخر قبل إرفاق المعالج المقصود. راجع الاستقلال وحدود الموارد قبل استبدال المسار المتتابع ببدء متزامن.
import 'dart:async';
Future<int> countBatch(int count) async => count;
Future<void> main() async {
final first = countBatch(2);
final second = countBatch(3);
final results = await Future.wait<int>(<Future<int>>[first, second]);
print(results[0] + results[1]);
}
5
المخرج المتوقع 5. يحدد ترتيب المدخل مواضع results. لا يقدم المثال إدخالا وإخراجا أو تجربة توقيت أو إنشاء عازل، ولم يُنفّذ باستخدام Dart.
انتظر داخل الحد الذي يترجم الخطأ
ليس try متزامنا حول إنشاء المهمة معالجا عاما لفشلها اللاحق. انتظر Future داخل try المقصودة عند استخدام async، أو أرفق سلسلة معالجة أخطاء مناسبة. يلتقط المثال FormatException معلنة بعد الانتظار ويطبع رسالة آمنة ثابتة. قد يخفي catch أوسع عيوبا برمجية أو يسمي فشلا غير مرتبط خطأ. احفظ سياقا مفيدا للتشخيص دون كشف بيانات حساسة. لا يعكس الانتظار والالتقاط أثرا خارجيا اكتمل قبل الإبلاغ عن الإخفاق.
اجعل الإتمام والتنظيف ظاهرين
تأتي علامة finally في البرنامج بعد مسار قيمة أو إخفاق ملتقط، لكنها لا تثبت إغلاق مورد حقيقي. تتيح Future<void> main تمثيل اكتمال عمل المدخل غير المتزامن. لا تُعلن نجاحا قبل اكتمال Future مؤثرة إلا إذا أعاد المنتج صراحة قبولا أو انتظارًا بمسار متابعة مملوك. إذا غادر المستدعي الشاشة أو الطلب، فحدّد من يظل مالك العملية وخطئها اللاحق، ولا تتركها مهمة منفصلة بالمصادفة.
import 'dart:async';
Future<int> loadCount() async {
throw const FormatException('synthetic invalid count');
}
Future<void> main() async {
try {
final count = await loadCount();
print(count);
} on FormatException {
print('invalid count');
} finally {
print('finished');
}
}
invalid count
finished
المخرج المتوقع invalid count ثم finished. الاستثناء اصطناعي ولا يُتصل بمزود، ولا يُدعى تنفيذ مترجم أو بيئة تشغيل.
ليست مهلة Future إلغاء عاما للعملية
تغير Future.timeout ما تبلغه Future المنتظرة بعد حد الزمن، ولا توقف عموما عملية المصدر. ولا تتراجع Future.wait تلقائيا عن آثار العمليات الأخرى أو تلغيها عند الفشل. يحتاج الإلغاء دعم الواجهة أو المورد أو بروتوكولا تعاونيا صريحا. قد توثق unawaited تعمد عدم الانتظار، لكنها لا تستهلك الأخطاء أو تمنح مالكا. حدّد الاستعلام عن النتيجة وقواعد إعادة الكتابة البعيدة. تقدم الدورة مصادر محللة فقط ولا تدعي اختبار مجدول أو توقيت أو شبكة أو إلغاء أو موثوقية.
الأخطاء الشائعة وإصلاحها
تؤخر دالة async معالجة الأحداث أثناء الحساب.
- لماذا يحدث؟
- اختلطت الصياغة غير المتزامنة بعازل تنفيذ مستقل.
- كيف تصلحه؟
- افصل الحساب أو حدّه واختر استراتيجية عوازل مدعومة عند تبريرها.
- كيف تتجنب تكراره؟
- صنّف العمل حسابا متزامنا أو انتظارًا غير متزامن قبل التحسين.
يفلت خطأ Future اللاحق من try المقصودة.
- لماذا يحدث؟
- أنشأ الحد المهمة دون انتظارها أو إرفاق معالجة خطأ.
- كيف تصلحه؟
- راقب Future مبكرا داخل حد الخطأ الصحيح.
- كيف تتجنب تكراره؟
- اطلب مالكا لكل Future مؤثرة ولكل إخفاق لها.
تعاد كتابة انتهت مهلتها كأنها لم تحدث.
- لماذا يحدث؟
- اختلط انتهاء الانتظار بإلغاء بعيد أو تراجع.
- كيف تصلحه؟
- استخدم استعلام نتيجة مدعوما أو بروتوكول هوية طلب ثابتة.
- كيف تتجنب تكراره؟
- نمذج النتائج المجهولة صراحة قبل إضافة الإعادة.
اختبر فهمك
1. هل تجعل إضافة unawaited إلى استدعاء مزود يُترك دون انتظار أخطاءه آمنة؟
اعرض الحل المشروح
لا. توثق القصد للتحليل ولا تركب معالج خطأ أو تلغي العمل أو تحدد مراقب النهاية. امنح العملية مالكا وسياسة خطأ صريحين أو انتظرها ضمن عمر المستدعي. وإذا لزم إنجاز خلفي دائم فصمّم حالة عمل دائمة، ولا تفترض نجاة Future في الذاكرة من فقد العملية.
2. متى تبدأ طلبي دفعتين قبل انتظار أي نتيجة؟
اعرض الحل المشروح
عندما يسمح ترتيب العمل واعتماديات الموارد بالتداخل، ويستطيع التطبيق ملاحظة النجاح والفشل لكليهما مبكرا. حد التوازي إذا نما المدخل. ليس إنشاء Futures كثيرة سياسة سعة، ولا يمحو فشل النتيجة المشتركة أثرا أنجزه طلب آخر. أبق نتيجة المستخدم والاستعادة صريحتين.
أهم ما تعلمته
- تمثل Future إتماما لاحقا، لا توازيا أو إلغاء تلقائيين.
- تحتاج كل عملية غير متزامنة بدأت إلى مالك لنتيجتها وخطئها.