طلب fetch عالق وما بيخلص؟ حطله مهلة بـ AbortSignal.timeout
مرّق لـ fetch خيار signal: AbortSignal.timeout(5000)، فبيوقف الطلب بعد 5 ثواني وبيرمي TimeoutError. وإذا بدك كمان زر إلغاء، اجمع الإشارتين بـ AbortSignal.any.

صفحتك بتطلب بيانات من خدمة تانية، وهالخدمة علقت. ما رجعت غلط، وما رجعت جواب، والمستخدم عم يتطلّع على دولاب تحميل ما بيخلص. السبب سطر fetch واحد ما إله حد للوقت. بآخر هالمقال رح تعرف تحطله مهلة بسطر، وتفرّقها عن إلغاء المستخدم.
شو هو AbortSignal.timeout؟
الـ AbortSignal.timeout() دالة بترجّع إشارة إلغاء بتوقف لحالها بعد عدد ميلي ثانية بتحدده إنت.
حسب صفحة AbortSignal.timeout() على MDN، الإشارة بتوقف بخطأ اسمه TimeoutError لما يخلص الوقت. والميزة متاحة بكل المتصفحات من نيسان 2024. وبـ Node.js، توثيق الـ globals بيقول إنها انضافت بـ v17.3.0 وv16.14.0.
ليش طلب fetch بيعلق؟
طلب fetch بيعلق لأنو بيستنى الطرف التاني يرد، وإذا ما عطيته إشارة إلغاء، ما في شي بيقلّه «بس، خلص».
الغلطة هون منطقية مش تقنية: منكتب الكود على أساس إنو الخدمة يا بترد يا بترمي غلط. بس في حالة تالتة، الخدمة ما بتعمل ولا شي، وهي يلي ما منحسبلها حساب. فالـ try/catch يلي كتبته ما بيوصله ولا خطأ، والمستخدم بيضل ناطر.
كيف تحط مهلة لطلب fetch؟
بتحط مهلة لما تمرّق لـ fetch خيار signal قيمته AbortSignal.timeout() مع عدد الميلي ثانية.
try {
const res = await fetch(url, { signal: AbortSignal.timeout(5000) });
const data = await res.json();
render(data);
} catch (err) {
if (err.name === "TimeoutError") {
showMessage("The service is slow. Try again.");
} else if (err.name === "AbortError") {
// the request was aborted another way
} else {
throw err;
}
}هون الطلب بيوقف بعد 5000 ميلي ثانية، يعني 5 ثواني، متل مثال MDN نفسه. والفرق بين الخطأين بيقلّك شو صار:
TimeoutError: المهلة خلصت. هاد مكان رسالة «الخدمة بطيئة، جرّب كمان مرة».AbortError: الطلب انلغى بطريقة تانية، متل زر الإيقاف بالمتصفح أو إغلاق التبويب حسب مثال MDN.أي خطأ تاني، متل مشكلة شبكة، رجّعه لفوق ولا تبلعه.
كيف تجمع المهلة مع زر إلغاء؟
بتجمع المهلة مع زر إلغاء بـ AbortSignal.any(): بتعطيه لستة إشارات، وبيرجّع إشارة وحدة بتوقف أول ما توقف أي وحدة منهن.
const userCancel = new AbortController();
cancelButton.addEventListener("click", () => userCancel.abort());
const signal = AbortSignal.any([
userCancel.signal,
AbortSignal.timeout(5 * 60 * 1000),
]);
const res = await fetch(fileUrl, { signal });هيك التحميل بيوقف إذا المستخدم كبس الزر، أو إذا مرقت 5 دقايق، أيهن أول. وبالـ catch بتفرّق بينهن متل فوق: AbortError للزر، وTimeoutError للمهلة. حسب صفحة AbortSignal.any() على MDN، الدالة متاحة بكل المتصفحات من آذار 2024، وبـ Node.js انضافت بـ v20.3.0 وv18.17.0.
ليش المهلة ما خلصت بوقتها؟
المهلة بتنحسب على الوقت الفعّال مش الوقت يلي مرق، فبعض الوقت ما بينعدّ.
صفحة MDN بتقول إنو المهلة بتوقف فعلياً إذا الكود عم يشتغل بـ worker موقوف، أو الصفحة بالـ bfcache (الكاش يلي بيرجّع الصفحة لما تكبس رجوع). فإذا عم تجرّب المهلة، خلّيك عالصفحة نفسها وما تروح عنها وترجع، أو اطلب من سيرفر بطيء عن قصد.
من وين تبلّش هلق؟
دوّر بمشروعك على كل fetch( ما فيه signal، وابلّش بالطلبات يلي بتوقف عليها الصفحة: تسجيل الدخول، والدفع، وأول بيانات بتنعرض. حطلها مهلة، واكتب رسالة واضحة لـ TimeoutError.
وإذا الطلب البطيء عم يوصل لقاعدة بياناتك، المهلة بتحمي المستخدم بس: السبب بتلاقيه لما تقرا EXPLAIN ANALYZE. ولأدوات تانية بالمتصفح بتوفّر عليك مكتبات، شوف كمان structuredClone للنسخ العميق، وإذا عم ترتّب شو تتعلم بعدين، خارطة طريق المبرمج 2026.
كم طلب fetch بلا مهلة عندك هلق بمسار تسجيل الدخول؟
أسئلة شائعة
هل AbortSignal.timeout بيشتغل بـ Node.js؟
إي. توثيق Node بيقول إنو انضاف بالنسختين v17.3.0 وv16.14.0، وfetch نفسه صار ثابت بـ v21.0.0، فبتقدر تستعمل نفس الكود يلي بالمتصفح.
ليش المهلة ما خلصت لما رحت عن الصفحة ورجعت بزر الرجوع؟
لأنو MDN بتقول إنو المهلة بتنحسب على الوقت الفعّال مش الوقت يلي مرق، فبتوقف فعلياً إذا الكود بـ worker موقوف أو الصفحة بالـ bfcache.
قديش لازم تكون المهلة؟
على قد الطلب. طلب بيانات صغير بيكفيه ثواني قليلة، وتحميل ملف كبير بدّه دقايق. قيس كم بياخد الطلب عادة عندك، وحط المهلة فوقه بشوي.


