تقنية

رفض Promise.all: لماذا تظهر نتائج بعد رسالة الخطأ؟

لقطات تجربتنا: الكل معلق، ثم C بقيمة29 وB مرفوض وA معلق عند رفض المجموعة، ثم A بقيمة17.
قرأنا رفض المجموعة قبل إكمال A؛ كل حالة هنا من اختبارنا المحلي.

رفض Promise.all لا يلغي العمليات الأخرى تلقائيا؛ إنه رفض للوعد الذي يجمع نتائجها. يمكن أن تستقر وعود أخرى بعد ظهور هذا الرفض. [1]

الخلاصة السريعة

  • Promise.all يرفض عند رفض أحد مدخلاته. [1]
  • في تجربتنا ظهر رفض المجموعة بينما بقي A معلقا.
  • أكملنا A لاحقا، فقرأنا سجلا نهائيا لكل الوعود.
  • يعيد allSettled السجلات بترتيب المدخلات، لا ترتيب اكتمالها. [2]

ثلاثة وعود نتحكم في نهاياتها

أنشأنا ثلاثة وعود أسميناها A وB وC، وأدخلناها بهذا الترتيب في عمليتي الجمع. احتفظنا لكل واحد بدالة تقبله وأخرى ترفضه، لكي نحدد خطوات المثال بأنفسنا. لا تمثل الأسماء ملفات يجري تنزيلها، ولا مهاما أرسلناها إلى خدمة.

بدأت الوعود الثلاثة معلقة. قبل تغيير أي منها جهزنا Promise.all وسجل allSettled. ثم قبلنا C بالقيمة 29، ورفضنا B بالنص B-failed. تركنا A بلا قبول أو رفض في تلك اللحظة. الأرقام والنص اختيارات تعليمية ثابتة وليست قياسات أداء.

نفذنا التجربة في Node v24.19.0 وفي Edge 155.0.4283.45، وتطابقت النتائج. لم نستخدم مؤقتات أو طلبات شبكة. لهذا نكتب ترتيب خطوات واضحا بدلا من ادعاء أن مهمة ما استغرقت عددا معينا من الملّي ثانية.

لحظة الرفض لا تصف الحالات كلها

وصلنا إلى معالج رفض المجموعة وقرأنا B-failed. كان C مقبولا بالفعل، وB مرفوضا، بينما لم نستدع أيا من دالتي A. كذلك لم يكن المعالج النهائي لسجل allSettled قد اكتمل. احتفظنا بهذه اللقطة قبل الخطوة التالية.

لا توجد في اللقطة ثلاثة إخفاقات. لدينا إخفاق واحد معلن وقيمة واحدة متاحة ووعد لم نحسمه بعد. لو حوّلنا صف المجموعة المرفوض إلى ثلاث بطاقات حمراء، لأضفنا إلى المثال حالتين لم تقعَا فيه.

بعد تسجيل الرفض استدعينا دالة قبول A بالقيمة 17. اكتمل بعدها السجل النهائي وحمل نتيجة A. هذه الخطوة قابلة لإعادة التنفيذ في الشيفرة؛ لا نستنتج استمرار الوعد من مجرد غياب رسالة إلغاء.

اقرأ السجل النهائي حقلا حقلا

ينتظر allSettled استقرار المدخلات، ثم يعطي لكل منها status، ومعه value عند القبول أو reason عند الرفض. ترتيب السجلات يطابق ترتيب الوعود المدخلة. [2]

كان أول سجل في ناتجنا خاصا بـA: حالته fulfilled وقيمته 17. أما الثاني فخاص بـB: حالته rejected وسببه B-failed. والثالث خاص بـC: حالته fulfilled وقيمته 29. لم نضع قيمة نجاح بديلة في سجل B، ولم ننقل C إلى البداية لأنه استقر أولا.

حافظ على الفرق بين سجل الخطوات وجدول النتيجة. كتبنا في الأول C ثم B ثم A؛ أما الصفوف النهائية فكانت A ثم B ثم C. يمكنك وضع الحرف بجانب كل موضع من المدخلات قبل تشغيل المثال، ثم مطابقة الجدول معه بعد انتهائه.

موضع المدخلالحالةالقيمة أو السبب
Afulfilledvalue: 17
Brejectedreason: B-failed
Cfulfilledvalue: 29
السجلات النهائية بترتيب المدخلات: A مقبول17، وB مرفوض بسببB-failed، وC مقبول29؛ أسفلها اختبار نجاح مستقل.
الصفوف النهائية مرتبة A ثم B ثم C، بينما خطواتنا حسمت C ثم B ثم A.

شيفرة تعيد تسلسل الرفض ثم الاكتمال

جهزنا معالج catch لقراءة سبب الرفض، ثم أكملنا A خارج ذلك المعالج. القراءة الثانية تنتظر السجل الكامل. لا تحول هذه الشيفرة سبب B إلى قيمة نجاح له. [1]

شغلنا المقطع المعروض نفسه في البيئتين. كانت الطباعة الأولى النص B-failed، والطباعة الثانية المصفوفة الموصوفة في الجدول. إنشاء الوعود يقع داخل run؛ لذا يعيد استدعاؤها بناء مدخلات جديدة بدلا من استعمال وعود حسمناها سابقا.

async function run() {
  function gate() {
    let ok,bad;
    const p=new Promise((r,j)=>{
      ok=r; bad=j;
    });
    return {p,ok,bad};
  }
  const a=gate(),
    b=gate(),c=gate();
  const input=[a.p,b.p,c.p];
  const all=Promise.all(input);
  const final=
    Promise.allSettled(input);
  c.ok(29);
  b.bad("B-failed");
  try { await all; }
  catch(e) { console.log(e); }
  a.ok(17);
  console.log(await final);
}
run();

[1] [2]

اختبار مقابل وحدود ما تعلمناه

أعدنا التجربة من الصفر بفرق واحد: قبلنا B بالقيمة 23 بدلا من رفضه. أبقينا ترتيب الحسم C ثم B ثم A. هذه المرة قبلت المجموعة وأعادت القيم 17 ثم 23 ثم 29. لم نحصل على هذا المسار باستبدال كلمة في سجل الرفض القديم؛ نفذنا مجموعة وعود جديدة.

يساعد هذا المقابل على فحص توقعين منفصلين في مثالنا. تغيير مصير B غيّر مصير المجموعة، لكنه لم يجعل ترتيب الحسم هو ترتيب القيم في نتيجتها. وثبتت قيمة A النهائية في المسارين رغم اختلاف ما رأيناه قبل إكمالها.

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

المراجع

  1. MDN — Promise.all
    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all
  2. MDN — Promise.allSettled
    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/allSettled
أُعد بمساعدة الذكاء الاصطناعي؛ مراجعة تحريرية آلية، دون مراجعة بشرية أو اعتماد مهني. تاريخ الإعداد13 أكتوبر2026.

أُعدّ هذا المقال بمساعدة الذكاء الاصطناعي وراجعته أدوات ذكاء اصطناعي. لا يُنسب إلى مراجع بشري أو خبير مستقل. منهجية المحتوى.